Skip to content

Commit

Permalink
Implemented first draft of xml import pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
elrnv committed Nov 29, 2020
1 parent b665df5 commit 712a888
Show file tree
Hide file tree
Showing 14 changed files with 5,171 additions and 1,453 deletions.
12 changes: 9 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ nom = { version = "3", features = ["verbose-errors"] }
num-traits = "0.2"
num-derive = "0.3"
byteorder = "1.3"
buffer = { package = "data-buffer", version = "0.7", features = ["numeric"] }
quick-xml = { version = "0.18", features = ["serialize"] }
serde = { version = "1.0", features = ["derive"] }
base64 = "0.12"
reinterpret = { version = "0.2", optional = true }
quick-xml = { path = "../quick-xml", version = "0.18", features = ["serialize"], optional = true }
serde = { version = "1.0", features = ["derive"], optional = true }

[features]
default = ["xml"]
xml = ["quick-xml", "serde", "reinterpret"]
unstable = []
27 changes: 14 additions & 13 deletions assets/cube.pvtp
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
<?xml version="1.0"?>
<VTKFile type="PPolyData" version="0.1" byte_order="LittleEndian">
<PPolyData GhostLevel="0">
<PPointData Scalars="my_scalars">
<PDataArray type="Float32" Name="my_scalars"/>
</PPointData>
<PCellData Scalars="cell_scalars" Normals="cell_normals">
<PDataArray type="Int32" Name="cell_scalars"/>
<PDataArray type="Float32" Name="cell_normals" NumberOfComponents="3"/>
</PCellData>
<PPoints>
<PDataArray type="Float32" NumberOfComponents="3"/>
</PPoints>
<Piece Source="polyEx0.vtp"/>
</PPolyData>
<PPolyData GhostLevel="0">
<PPointData Scalars="my_scalars">
<PDataArray type="Float32" Name="my_scalars"/>
</PPointData>
<PCellData Scalars="cell_scalars" Normals="cell_normals">
<PDataArray type="Int32" Name="cell_scalars"/>
<PDataArray type="Float32" Name="cell_normals" NumberOfComponents="3"/>
</PCellData>
<PPoints>
<PDataArray type="Float32" NumberOfComponents="3"/>
</PPoints>
<Piece Source="polyEx0.vtp"/>
<Piece Source="polyEx0.vtp"/>
</PPolyData>
</VTKFile>
33 changes: 0 additions & 33 deletions assets/cube.vtp

This file was deleted.

50 changes: 32 additions & 18 deletions assets/polyEx0.vtp
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
<?xml version="1.0"?>
<VTKFile type="PolyData" version="0.1" byte_order="LittleEndian">
<PolyData>
<Piece NumberOfPoints="8" NumberOfVerts="0" NumberOfLines="0"NumberOfStrips="0" NumberOfPolys="6">
<Points>
<DataArray type="Float32" NumberOfComponents="3" format="ascii">000100110010001101111011</DataArray>
</Points>
<PointData Scalars="my_scalars">
<DataArray type="Float32" Name="my_scalars" format="ascii">01234567</DataArray>
</PointData>
<CellData Scalars="cell_scalars" Normals="cell_normals">
<DataArray type="Int32" Name="cell_scalars" format="ascii">012345</DataArray>
<DataArray type="Float32" Name="cell_normals"NumberOfComponents="3" format="ascii">00-10010-10010-100100</DataArray>
</CellData>
<Polys>
<DataArray type="Int32" Name="connectivity" format="ascii">012345670154237604731265</DataArray>
<DataArray type="Int32" Name="offsets" format="ascii">4812162024</DataArray>
</Polys>
</Piece>
</PolyData>
<PolyData>
<Piece NumberOfPoints="8" NumberOfVerts="0" NumberOfLines="0"
NumberOfStrips="0" NumberOfPolys="6">
<Points>
<DataArray type="Float32" NumberOfComponents="3" format="ascii">
0 0 0 1 0 0 1 1 0 0 1 0 0 0 1 1 0 1 1 1 1 0 1 1
</DataArray>
</Points>
<PointData Scalars="my_scalars">
<DataArray type="Float32" Name="my_scalars" format="ascii">
0 1 2 3 4 5 6 7
</DataArray>
</PointData>
<CellData Scalars="cell_scalars" Normals="cell_normals">
<DataArray type="Int32" Name="cell_scalars" format="ascii">
0 1 2 3 4 5
</DataArray>
<DataArray type="Float32" Name="cell_normals"
NumberOfComponents="3" format="ascii">
0 0 -1 0 0 1 0 -1 0 0 1 0 -1 0 0 1 0 0
</DataArray>
</CellData>
<Polys>
<DataArray type="Int32" Name="connectivity" format="ascii">
0 1 2 3 4 5 6 7 0 1 5 4 2 3 7 6 0 4 7 3 1 2 6 5
</DataArray>
<DataArray type="Int32" Name="offsets" format="ascii">
4 8 12 16 20 24
</DataArray>
</Polys>
</Piece>
</PolyData>
</VTKFile>
129 changes: 103 additions & 26 deletions src/basic.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use nom::{digit, IResult, Needed};

use crate::IOBuffer;
use byteorder::{ByteOrder, NativeEndian};
use num_traits::Zero;
use std::any::Any;
use std::str::{self, FromStr};

use byteorder::ByteOrder;
use nom::{digit, IResult, Needed};
use num_traits::Zero;

use crate::model::IOBuffer;

/// This enum indicates if bulk data is saved in binary.
/// NOTE: VTK files are saved in ASCII format with bulk data optionally saved in
/// Binary among ASCII type keywords. Binary data must be placed into the file
Expand Down Expand Up @@ -157,25 +158,101 @@ where
)
}

pub struct DataParser<BO: ByteOrder = NativeEndian>(::std::marker::PhantomData<BO>);
// A trait identifying all scalar types supported by VTK.
pub trait Scalar: FromStr + FromAscii + FromBinary {}
macro_rules! impl_scalar {
($($type:ty),* $(,)*) => {
$(
impl Scalar for $type {}
)*
}
}

impl_scalar!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64);

/// Parse a set of typed numbers into an `IOBuffer`.
pub fn parse_data_buffer<T, BO>(input: &[u8], n: usize, ft: FileType) -> IResult<&[u8], IOBuffer>
where
T: Scalar + Any + Clone + Zero + ::std::fmt::Debug,
BO: ByteOrder,
IOBuffer: From<Vec<T>>,
{
parse_data_vec::<T, BO>(input, n, ft).map(IOBuffer::from)
}

/// Parse a set of unsigned bytes into an `IOBuffer`.
pub fn parse_data_buffer_u8(input: &[u8], n: usize, ft: FileType) -> IResult<&[u8], IOBuffer> {
parse_data_vec_u8(input, n, ft).map(IOBuffer::from)
}

/// Parse a set of signed bytes into an `IOBuffer`.
pub fn parse_data_buffer_i8(input: &[u8], n: usize, ft: FileType) -> IResult<&[u8], IOBuffer> {
parse_data_vec_i8(input, n, ft).map(IOBuffer::from)
}

/// Parse a set of bits into an `IOBuffer`.
pub fn parse_data_bit_buffer(input: &[u8], n: usize, ft: FileType) -> IResult<&[u8], IOBuffer> {
parse_data_bit_vec(input, n, ft).map(IOBuffer::from)
}

impl<BO: ByteOrder> DataParser<BO> {
/// Parse a set of typed numbers into an `IOBuffer`.
pub fn data_buffer<T>(input: &[u8], n: usize, ft: FileType) -> IResult<&[u8], IOBuffer>
where
T: FromStr + Any + Clone + Zero + FromBinary + FromAscii + ::std::fmt::Debug,
{
Self::data_vec::<T>(input, n, ft).map(IOBuffer::from)
/// Parse a set of typed numbers into a `Vec`.
pub fn parse_data_vec<T, BO>(input: &[u8], n: usize, ft: FileType) -> IResult<&[u8], Vec<T>>
where
T: Scalar,
BO: ByteOrder,
{
match ft {
FileType::ASCII => many_m_n!(input, n, n, ws!(T::from_ascii)),
FileType::Binary => many_m_n!(input, n, n, T::from_binary::<BO>),
}
}

/// Parse a set of typed numbers into a `Vec`.
pub fn data_vec<T>(input: &[u8], n: usize, ft: FileType) -> IResult<&[u8], Vec<T>>
where
T: FromStr + FromAscii + FromBinary,
{
match ft {
FileType::ASCII => many_m_n!(input, n, n, ws!(T::from_ascii)),
FileType::Binary => many_m_n!(input, n, n, T::from_binary::<BO>),
/// Parse a set of unsigned bytes into a `Vec`.
pub fn parse_data_vec_u8(input: &[u8], n: usize, ft: FileType) -> IResult<&[u8], Vec<u8>> {
match ft {
FileType::ASCII => many_m_n!(input, n, n, ws!(u8::from_ascii)),
FileType::Binary => {
// If expecting bytes, byte order doesn't matter, just return the entire block.
if input.len() < n {
IResult::Incomplete(Needed::Size(n))
} else {
IResult::Done(&input[n..], input[0..n].to_vec())
}
}
}
}

/// Parse a set of signed bytes into a `Vec`.
pub fn parse_data_vec_i8(input: &[u8], n: usize, ft: FileType) -> IResult<&[u8], Vec<i8>> {
match ft {
FileType::ASCII => many_m_n!(input, n, n, ws!(i8::from_ascii)),
FileType::Binary => {
// If expecting bytes, byte order doesn't matter, just return the entire block.
// Unsafety is used here to avoid having to iterate.
if input.len() < n {
IResult::Incomplete(Needed::Size(n))
} else {
// SAFETY: All u8 are representable as i8 and both are 8 bits.
IResult::Done(
&input[n..],
unsafe { std::slice::from_raw_parts(input[0..n].as_ptr() as *const i8, n) }
.to_vec(),
)
}
}
}
}

pub fn parse_data_bit_vec(input: &[u8], n: usize, ft: FileType) -> IResult<&[u8], Vec<u8>> {
match ft {
FileType::ASCII => many_m_n!(input, n, n, ws!(u8::from_ascii)),
FileType::Binary => {
let nbytes = n / 8 + if n % 8 == 0 { 0 } else { 1 };
if input.len() < nbytes {
IResult::Incomplete(Needed::Size(nbytes))
} else {
IResult::Done(&input[nbytes..], input[0..nbytes].to_vec())
}
}
}
}
Expand Down Expand Up @@ -215,30 +292,30 @@ mod tests {
}
#[test]
fn data_test() {
let f = <DataParser>::data_buffer::<f32>("".as_bytes(), 0, FileType::ASCII);
let f = parse_data_buffer::<f32, BigEndian>("".as_bytes(), 0, FileType::ASCII);
assert_eq!(
f,
IResult::Done("".as_bytes(), IOBuffer::from(Vec::<f32>::new()))
);
let f = <DataParser>::data_buffer::<f32>("3".as_bytes(), 1, FileType::ASCII);
let f = parse_data_buffer::<f32, BigEndian>("3".as_bytes(), 1, FileType::ASCII);
assert_eq!(
f,
IResult::Done("".as_bytes(), IOBuffer::from(vec![3.0f32]))
);
let f = <DataParser>::data_buffer::<f32>("3 32".as_bytes(), 2, FileType::ASCII);
let f = parse_data_buffer::<f32, BigEndian>("3 32".as_bytes(), 2, FileType::ASCII);
assert_eq!(
f,
IResult::Done("".as_bytes(), IOBuffer::from(vec![3.0f32, 32.0]))
);
let f = <DataParser>::data_buffer::<f32>("3 32 32.0 4e3".as_bytes(), 4, FileType::ASCII);
let f = parse_data_buffer::<f32, BigEndian>("3 32 32.0 4e3".as_bytes(), 4, FileType::ASCII);
assert_eq!(
f,
IResult::Done(
"".as_bytes(),
IOBuffer::from(vec![3.0f32, 32.0, 32.0, 4.0e3])
)
);
let f = <DataParser>::data_buffer::<f64>("3 32 32.0 4e3".as_bytes(), 4, FileType::ASCII);
let f = parse_data_buffer::<f64, BigEndian>("3 32 32.0 4e3".as_bytes(), 4, FileType::ASCII);
assert_eq!(
f,
IResult::Done(
Expand Down
Loading

0 comments on commit 712a888

Please sign in to comment.