use byteorder::{BigEndian, ByteOrder, LittleEndian, NativeEndian};
use nom::{self, eol, ErrorKind, IResult};
use num_traits::FromPrimitive;
use std::marker::PhantomData;
use std::str;
pub use crate::basic::*;
use crate::model::*;
use crate::IOBuffer;
named!(version<&[u8], Version>, sp!(
do_parse!(
tag!("#") >>
tag_no_case!("vtk") >>
tag_no_case!("DataFile") >>
tag_no_case!("Version") >>
ver: separated_pair!(u8_b, tag!("."), u8_b) >>
eol >>
(Version::new(ver))
)
)
);
named!(file_type<&[u8], FileType>,
alt!( tag_no_case!("ASCII") => { |_| FileType::ASCII } |
tag_no_case!("BINARY") => { |_| FileType::Binary } ) );
named!(title<&[u8], &str>, map_res!(
do_parse!(
ttl: take_until!("\n") >>
eol >>
(ttl)),
str::from_utf8 )
);
named!(header<&[u8], (Version, String, FileType)>, sp!(
do_parse!(
ver: version >>
ttl: title >>
ft: file_type >>
((ver, String::from(ttl), ft))
)
)
);
named!(data_type< &[u8], DataType >, alt!(
tag_no_case!("bit") => { |_| DataType::Bit } |
tag_no_case!("int") => { |_| DataType::Int } |
tag_no_case!("char") => { |_| DataType::Char } |
tag_no_case!("long") => { |_| DataType::Long } |
tag_no_case!("short") => { |_| DataType::Short } |
tag_no_case!("float") => { |_| DataType::Float } |
tag_no_case!("double") => { |_| DataType::Double } |
tag_no_case!("unsigned_int") => { |_| DataType::UnsignedInt } |
tag_no_case!("unsigned_char") => { |_| DataType::UnsignedChar } |
tag_no_case!("unsigned_long") => { |_| DataType::UnsignedLong } |
tag_no_case!("unsigned_short") => { |_| DataType::UnsignedShort } ));
named!(usize_b<&[u8], usize>, call!(integer) );
named!(u32_b<&[u8], u32>, call!(integer) );
named!(u8_b<&[u8], u8>, call!(integer) );
named!(f32_b<&[u8], f32>, call!(real::<f32>) );
named!(name, take_till!(|x: u8| " \t\n\r".as_bytes().contains(&x)));
enum Axis {
X,
Y,
Z,
}
pub struct VtkParser<BO: ByteOrder = NativeEndian>(PhantomData<BO>);
impl<BO: ByteOrder> VtkParser<BO> {
#[allow(unused_variables)]
fn points(input: &[u8], ft: FileType) -> IResult<&[u8], IOBuffer> {
do_parse!(
input,
n: ws!(do_parse!(tag_no_case!("POINTS") >> n: u32_b >> (n)))
>> vec: switch!(
do_parse!(
dt: sp!( data_type ) >>
tag!("\n") >>
(dt) ),
DataType::Float => call!( DataParser::<BO>::data_buffer::<f32>, 3*n as usize, ft ) |
DataType::Double => call!( DataParser::<BO>::data_buffer::<f64>, 3*n as usize, ft ) )
>> (vec)
)
}
fn cells<'a>(input: &'a [u8], tag: &'static str, ft: FileType) -> IResult<&'a [u8], Cells> {
do_parse!(
input,
n: ws!(do_parse!(tag_no_case!(tag) >> n: u32_b >> (n)))
>> size: sp!(u32_b)
>> tag!("\n")
>> data: call!(DataParser::<BO>::data_vec::<u32>, size as usize, ft)
>> (Cells {
num_cells: n,
vertices: data
})
)
}
#[allow(unused_variables)]
fn coordinates(input: &[u8], axis: Axis, ft: FileType) -> IResult<&[u8], IOBuffer> {
let tag = match axis {
Axis::X => "X_COORDINATES",
Axis::Y => "Y_COORDINATES",
Axis::Z => "Z_COORDINATES",
};
do_parse!(
input,
n: ws!(do_parse!(tag_no_case!(tag) >> n: u32_b >> (n)))
>> vec: switch!(
do_parse!(
dt: sp!( data_type ) >>
tag!("\n") >>
(dt) ),
DataType::Float => call!( DataParser::<BO>::data_buffer::<f32>, n as usize, ft ) |
DataType::Double => call!( DataParser::<BO>::data_buffer::<f64>, n as usize, ft ) )
>> (vec)
)
}
fn meta(input: &[u8]) -> IResult<&[u8], ()> {
complete!(
input,
ws!(do_parse!(
tag_no_case!("METADATA") >> take_until!("\n\n") >> ()
))
)
}
fn attribute_data(
input: &[u8],
n: usize,
data_type: DataType,
ft: FileType,
) -> IResult<&[u8], IOBuffer> {
match data_type {
DataType::Bit => DataParser::<BO>::data_buffer::<u8>(input, n, ft),
DataType::UnsignedChar => DataParser::<BO>::data_buffer::<u8>(input, n, ft),
DataType::Char => DataParser::<BO>::data_buffer::<i8>(input, n, ft),
DataType::UnsignedShort => DataParser::<BO>::data_buffer::<u16>(input, n, ft),
DataType::Short => DataParser::<BO>::data_buffer::<i16>(input, n, ft),
DataType::UnsignedInt => DataParser::<BO>::data_buffer::<u32>(input, n, ft),
DataType::Int => DataParser::<BO>::data_buffer::<i32>(input, n, ft),
DataType::UnsignedLong => DataParser::<BO>::data_buffer::<u64>(input, n, ft),
DataType::Long => DataParser::<BO>::data_buffer::<i64>(input, n, ft),
DataType::Float => DataParser::<BO>::data_buffer::<f32>(input, n, ft),
DataType::Double => DataParser::<BO>::data_buffer::<f64>(input, n, ft),
}
}
named!(
lookup_table,
alt_complete!(
sp!( do_parse!( tag_no_case!("LOOKUP_TABLE") >> n: name >> (n) ) ) |
eof!() => { |_| "".as_bytes() } |
eol
)
);
fn attribute_scalars(
input: &[u8],
num_elements: usize,
ft: FileType,
) -> IResult<&[u8], (String, Attribute)> {
ws!(
input,
do_parse!(
tag_no_case!("SCALARS")
>> name: map_res!(name, str::from_utf8)
>> dt: data_type
>> num_comp: opt!(u8_b)
>> lookup_tbl_name: opt!(map_res!(Self::lookup_table, str::from_utf8))
>> data: call!(
Self::attribute_data,
num_comp.unwrap_or(1) as usize * num_elements,
dt,
ft
)
>> opt!(Self::meta)
>> ((
String::from(name),
Attribute::Scalars {
num_comp: num_comp.unwrap_or(1),
lookup_table: lookup_tbl_name.and_then(|x| if x == "default" {
None
} else {
Some(String::from(x))
}),
data
}
))
)
)
}
fn attribute_lookup_table(input: &[u8], ft: FileType) -> IResult<&[u8], (String, Attribute)> {
ws!(
input,
do_parse!(
tag_no_case!("LOOKUP_TABLE")
>> name: map_res!(name, str::from_utf8)
>> num_elements: u32_b
>> data: call!(
Self::attribute_data,
4 * num_elements as usize,
DataType::Float,
ft
)
>> opt!(Self::meta)
>> (String::from(name), Attribute::LookupTable { data })
)
)
}
fn attribute_color_scalars_data(
input: &[u8],
n: usize,
ft: FileType,
) -> IResult<&[u8], IOBuffer> {
match ft {
FileType::ASCII => Self::attribute_data(input, n, DataType::Float, ft),
FileType::Binary => Self::attribute_data(input, n, DataType::UnsignedChar, ft),
}
}
fn attribute_color_scalars(
input: &[u8],
num_elements: usize,
ft: FileType,
) -> IResult<&[u8], (String, Attribute)> {
ws!(
input,
do_parse!(
tag_no_case!("COLOR_SCALARS")
>> name: map_res!(name, str::from_utf8)
>> num_comp: u8_b
>> data: call!(
Self::attribute_color_scalars_data,
num_comp as usize * num_elements,
ft
)
>> opt!(Self::meta)
>> ((
String::from(name),
Attribute::ColorScalars { num_comp, data }
))
)
)
}
fn attribute_vectors(
input: &[u8],
num_elements: usize,
ft: FileType,
) -> IResult<&[u8], (String, Attribute)> {
ws!(
input,
do_parse!(
tag_no_case!("VECTORS")
>> name: map_res!(name, str::from_utf8)
>> dt: data_type
>> data: call!(Self::attribute_data, 3 * num_elements, dt, ft)
>> opt!(Self::meta)
>> (String::from(name), Attribute::Vectors { data })
)
)
}
fn attribute_normals(
input: &[u8],
num_elements: usize,
ft: FileType,
) -> IResult<&[u8], (String, Attribute)> {
ws!(
input,
do_parse!(
tag_no_case!("NORMALS")
>> name: map_res!(name, str::from_utf8)
>> dt: data_type
>> data: call!(Self::attribute_data, 3 * num_elements, dt, ft)
>> opt!(Self::meta)
>> (String::from(name), Attribute::Normals { data })
)
)
}
fn attribute_tex_coords(
input: &[u8],
num_elements: usize,
ft: FileType,
) -> IResult<&[u8], (String, Attribute)> {
ws!(
input,
do_parse!(
tag_no_case!("TEXTURE_COORDINATES")
>> name: map_res!(name, str::from_utf8)
>> dim: u8_b
>> dt: data_type
>> data: call!(Self::attribute_data, dim as usize * num_elements, dt, ft)
>> opt!(Self::meta)
>> (
String::from(name),
Attribute::TextureCoordinates { dim, data }
)
)
)
}
fn attribute_tensors(
input: &[u8],
num_elements: usize,
ft: FileType,
) -> IResult<&[u8], (String, Attribute)> {
ws!(
input,
do_parse!(
tag_no_case!("TENSORS")
>> name: map_res!(name, str::from_utf8)
>> dt: data_type
>> data: call!(Self::attribute_data, 9 * num_elements, dt, ft)
>> opt!(Self::meta)
>> (String::from(name), Attribute::Tensors { data })
)
)
}
fn attribute_field_array(input: &[u8], ft: FileType) -> IResult<&[u8], FieldArray> {
ws!(
input,
do_parse!(
name: map_res!(name, str::from_utf8)
>> num_comp: u32_b
>> num_tuples: u32_b
>> dt: data_type
>> data: call!(
Self::attribute_data,
(num_comp * num_tuples) as usize,
dt,
ft
)
>> opt!(Self::meta)
>> (FieldArray {
name: String::from(name),
num_comp,
data
})
)
)
}
fn attribute_field(input: &[u8], ft: FileType) -> IResult<&[u8], (String, Attribute)> {
ws!(
input,
do_parse!(
tag_no_case!("FIELD")
>> name: map_res!(name, str::from_utf8)
>> n: u32_b
>> data_array:
many_m_n!(
n as usize,
n as usize,
call!(Self::attribute_field_array, ft)
)
>> (String::from(name), Attribute::Field { data_array })
)
)
}
fn attribute(
input: &[u8],
num_elements: usize,
ft: FileType,
) -> IResult<&[u8], (String, Attribute)> {
ws!(
input,
alt!(
call!(Self::attribute_scalars, num_elements, ft)
| call!(Self::attribute_color_scalars, num_elements, ft)
| call!(Self::attribute_lookup_table, ft)
| call!(Self::attribute_vectors, num_elements, ft)
| call!(Self::attribute_normals, num_elements, ft)
| call!(Self::attribute_tex_coords, num_elements, ft)
| call!(Self::attribute_tensors, num_elements, ft)
| call!(Self::attribute_field, ft)
)
)
}
fn point_attributes(input: &[u8], ft: FileType) -> IResult<&[u8], Vec<(String, Attribute)>> {
ws!(
input,
alt_complete!(
do_parse!(
tag_no_case!("POINT_DATA") >>
n: sp!(u32_b) >>
vec: many0!( call!( Self::attribute, n as usize, ft ) ) >>
(vec)
) |
ws!( eof!() ) => { |_| Vec::new() }
)
)
}
fn cell_attributes(input: &[u8], ft: FileType) -> IResult<&[u8], Vec<(String, Attribute)>> {
ws!(
input,
alt_complete!(
do_parse!(
ws!( tag_no_case!("CELL_DATA") ) >>
n: sp!( u32_b ) >>
vec: many0!( call!( Self::attribute, n as usize, ft ) ) >>
(vec)
) |
ws!( eof!() ) => { |_| Vec::new() }
)
)
}
fn attributes(input: &[u8], ft: FileType) -> IResult<&[u8], Attributes> {
ws!(
input,
do_parse!(
c1: opt!(call!(Self::cell_attributes, ft))
>> p: opt!(call!(Self::point_attributes, ft))
>> c2: opt!(call!(Self::cell_attributes, ft))
>> (Attributes {
point: p.unwrap_or_default(),
cell: if let Some(c) = c1 {
c
} else {
c2.unwrap_or_default()
}
})
)
)
}
fn structured_points(input: &[u8], ft: FileType) -> IResult<&[u8], DataSet> {
ws!(
input,
do_parse!(
tag_no_case!("STRUCTURED_POINTS")
>> parms:
permutation!(
do_parse!(
tag_no_case!("DIMENSIONS")
>> nx: u32_b
>> ny: u32_b
>> nz: u32_b
>> ([nx, ny, nz])
),
do_parse!(
tag_no_case!("ORIGIN")
>> x: f32_b
>> y: f32_b
>> z: f32_b
>> ([x, y, z])
),
do_parse!(
alt_complete!(
tag_no_case!("SPACING") | tag_no_case!("ASPECT_RATIO")
) >> sx: f32_b
>> sy: f32_b
>> sz: f32_b
>> ([sx, sy, sz])
)
)
>> data: call!(Self::attributes, ft)
>> (DataSet::StructuredPoints {
dims: parms.0,
origin: parms.1,
spacing: parms.2,
data
})
)
)
}
fn structured_grid(input: &[u8], ft: FileType) -> IResult<&[u8], DataSet> {
ws!(
input,
do_parse!(
tag_no_case!("STRUCTURED_GRID")
>> dims: do_parse!(
tag_no_case!("DIMENSIONS")
>> nx: u32_b
>> ny: u32_b
>> nz: u32_b
>> ([nx, ny, nz])
)
>> points: call!(Self::points, ft)
>> opt!(Self::meta)
>> data: call!(Self::attributes, ft)
>> (DataSet::StructuredGrid { dims, points, data })
)
)
}
fn rectilinear_grid(input: &[u8], ft: FileType) -> IResult<&[u8], DataSet> {
ws!(
input,
do_parse!(
tag_no_case!("RECTILINEAR_GRID")
>> dims: do_parse!(
tag_no_case!("DIMENSIONS")
>> nx: u32_b
>> ny: u32_b
>> nz: u32_b
>> ([nx, ny, nz])
)
>> x_coords: call!(Self::coordinates, Axis::X, ft)
>> y_coords: call!(Self::coordinates, Axis::Y, ft)
>> z_coords: call!(Self::coordinates, Axis::Z, ft)
>> data: call!(Self::attributes, ft)
>> opt!(complete!(Self::meta))
>> (DataSet::RectilinearGrid {
dims,
x_coords,
y_coords,
z_coords,
data
})
)
)
}
fn field_data(input: &[u8], ft: FileType) -> IResult<&[u8], DataSet> {
let res = Self::attribute_field(input, ft);
match res {
IResult::Done(i, o) => {
if let (name, Attribute::Field { data_array }) = o {
IResult::Done(i, DataSet::Field { name, data_array })
} else {
IResult::Error(nom::Err::Code(ErrorKind::Custom(1u32)))
}
}
IResult::Incomplete(e) => IResult::Incomplete(e),
IResult::Error(e) => IResult::Error(e),
}
}
named!(pub cell_type<&[u8], CellType>,
map_opt!( u8_b, |x| CellType::from_u8(x) )
);
named!(pub cell_type_binary<&[u8], CellType>,
map_opt!( i32::from_binary::<BO>, |x| CellType::from_u8(x as u8) )
);
fn cell_type_data(input: &[u8], n: usize, ft: FileType) -> IResult<&[u8], Vec<CellType>> {
match ft {
FileType::ASCII => many_m_n!(input, n, n, ws!(Self::cell_type)),
FileType::Binary => many_m_n!(input, n, n, Self::cell_type_binary),
}
}
fn cell_types(input: &[u8], ft: FileType) -> IResult<&[u8], Vec<CellType>> {
do_parse!(
input,
ws!(tag_no_case!("CELL_TYPES"))
>> n: sp!(usize_b)
>> tag!("\n")
>> data: dbg!(call!(Self::cell_type_data, n, ft))
>> (data)
)
}
fn unstructured_grid(input: &[u8], ft: FileType) -> IResult<&[u8], DataSet> {
ws!(
input,
do_parse!(
tag_no_case!("UNSTRUCTURED_GRID")
>> p: call!(Self::points, ft)
>> opt!(Self::meta)
>> c: call!(Self::cells, "CELLS", ft)
>> ct: call!(Self::cell_types, ft)
>> data: call!(Self::attributes, ft)
>> (DataSet::UnstructuredGrid {
points: p,
cells: c,
cell_types: ct,
data
})
)
)
}
fn poly_data_topo(input: &[u8], ft: FileType) -> IResult<&[u8], PolyDataTopology> {
alt_complete!(
input,
map!(
call!(Self::cells, "LINES", ft),
|x| PolyDataTopology::Lines(x)
) | map!(call!(Self::cells, "POLYGONS", ft), |x| {
PolyDataTopology::Polygons(x)
}) | map!(call!(Self::cells, "VERTICES", ft), |x| {
PolyDataTopology::Vertices(x)
}) | map!(call!(Self::cells, "TRIANGLE_STRIPS", ft), |x| {
PolyDataTopology::TriangleStrips(x)
})
)
}
#[allow(unused_comparisons)]
fn poly_data(input: &[u8], ft: FileType) -> IResult<&[u8], DataSet> {
do_parse!(
input,
tag_no_case!("POLYDATA")
>> points: call!(Self::points, ft)
>> opt!(Self::meta)
>> topo: many_m_n!(0, 4, call!(Self::poly_data_topo, ft))
>> data: call!(Self::attributes, ft)
>> (DataSet::PolyData { points, topo, data })
)
}
fn dataset(input: &[u8], file_type: FileType) -> IResult<&[u8], DataSet> {
alt_complete!(
input,
do_parse!(
tag_no_case!("DATASET")
>> whitespace
>> tn: alt!(
call!(Self::poly_data, file_type)
| call!(Self::structured_grid, file_type)
| call!(Self::rectilinear_grid, file_type)
| call!(Self::structured_points, file_type)
| call!(Self::unstructured_grid, file_type)
)
>> (tn)
) | call!(Self::field_data, file_type)
)
}
fn vtk(input: &[u8]) -> IResult<&[u8], Vtk> {
complete!(
input,
ws!(do_parse!(
h: header
>> d: call!(Self::dataset, h.2)
>> (Vtk {
version: h.0,
title: h.1,
data: d
})
))
)
}
}
pub fn parse(input: &[u8]) -> IResult<&[u8], Vtk> {
<VtkParser>::vtk(input)
}
pub fn parse_le(input: &[u8]) -> IResult<&[u8], Vtk> {
VtkParser::<LittleEndian>::vtk(input)
}
pub fn parse_be(input: &[u8]) -> IResult<&[u8], Vtk> {
VtkParser::<BigEndian>::vtk(input)
}
#[cfg(test)]
mod tests {
use super::*;
use nom::IResult;
#[test]
fn file_type_test() {
let f = file_type("BINARY".as_bytes());
assert_eq!(f, IResult::Done(&b""[..], FileType::Binary));
let f = file_type("ASCII".as_bytes());
assert_eq!(f, IResult::Done(&b""[..], FileType::ASCII));
}
#[test]
fn version_test() {
let f = version("\t# vtk DataFile Version 2.0 \ntitle\n".as_bytes());
assert_eq!(f, IResult::Done("title\n".as_bytes(), Version::new((2, 0))));
}
#[test]
fn title_test() {
let f = title("This is a title\nBINARY".as_bytes());
assert_eq!(f, IResult::Done("BINARY".as_bytes(), "This is a title"));
}
#[test]
fn points_test() {
let in1 = "POINTS 0 float\n";
let in2 = "POINTS 3 float\n2 45 2 3 4 1 46 2 0\nother";
let f = <VtkParser>::points(in1.as_bytes(), FileType::ASCII);
assert_eq!(f, IResult::Done("".as_bytes(), Vec::<f32>::new().into()));
let f = <VtkParser>::points(in2.as_bytes(), FileType::ASCII);
assert_eq!(
f,
IResult::Done(
"other".as_bytes(),
vec![2.0f32, 45., 2., 3., 4., 1., 46., 2., 0.].into()
)
);
}
#[test]
fn cells_test() {
let in1 = "CELLS 0 0\n";
let in2 = "CELLS 1 3\n2 1 2\nother";
let f = <VtkParser>::cells(in1.as_bytes(), "CELLS", FileType::ASCII);
assert_eq!(
f,
IResult::Done(
"".as_bytes(),
Cells {
num_cells: 0,
vertices: vec![]
}
)
);
let f = <VtkParser>::cells(in2.as_bytes(), "CELLS", FileType::ASCII);
assert_eq!(
f,
IResult::Done(
"other".as_bytes(),
Cells {
num_cells: 1,
vertices: vec![2, 1, 2]
}
)
);
}
#[test]
fn cell_type_test() {
let f = <VtkParser>::cell_type("2".as_bytes());
assert_eq!(f, IResult::Done("".as_bytes(), CellType::PolyVertex));
let f = <VtkParser>::cell_type("10".as_bytes());
assert_eq!(f, IResult::Done("".as_bytes(), CellType::Tetra));
}
macro_rules! test {
($fn:ident ($in:expr, $($args:expr),*) => ($rem:expr, $out:expr)) => {
assert_eq!(<VtkParser>::$fn($in.as_bytes(), $($args),*), IResult::Done($rem.as_bytes(), $out.clone()));
};
($fn:ident ($in:expr) => ($rem:expr, $out:expr)) => {
assert_eq!(<VtkParser>::$fn($in.as_bytes()), IResult::Done($rem.as_bytes(), $out.clone()));
};
($fn:ident ($in:expr, $($args:expr),*) => $out:expr) => {
test!($fn($in, $($args),*) => ("", $out));
};
($fn:ident ($in:expr) => $out:expr) => {
test!($fn($in) => ("", $out));
}
}
#[test]
fn cell_types_test() {
let in1 = "CELL_TYPES 0\nother";
let out1 = Vec::<CellType>::new();
let in2 = "CELL_TYPES 3\n2 1 10\nother";
let out2 = vec![CellType::PolyVertex, CellType::Vertex, CellType::Tetra];
test!(cell_types(in1, FileType::ASCII) => ("other", out1));
test!(cell_types(in2, FileType::ASCII) => ("other", out2));
}
#[test]
fn unstructured_grid_test() {
let in1 = "UNSTRUCTURED_GRID\nPOINTS 4 float\n\
2 45 2 3 4 1 46 2 0 4 32 1\nCELLS 2 10\n4 0 1 2 3\n4 3 2 1 0
CELL_TYPES 2\n 10 10\nother";
let out1 = DataSet::UnstructuredGrid {
points: vec![2.0f32, 45., 2., 3., 4., 1., 46., 2., 0., 4., 32., 1.].into(),
cells: Cells {
num_cells: 2,
vertices: vec![4, 0, 1, 2, 3, 4, 3, 2, 1, 0],
},
cell_types: vec![CellType::Tetra; 2],
data: Attributes::new(),
};
test!(unstructured_grid(in1, FileType::ASCII) => ("other", out1));
}
#[test]
fn attribute_test() {
let in1 = "SCALARS cell_scalars int 1\n0 1 2 3 4 5";
let out1 = (
String::from("cell_scalars"),
Attribute::Scalars {
num_comp: 1,
lookup_table: None,
data: vec![0, 1, 2, 3, 4, 5].into(),
},
);
test!(attribute(in1, 6, FileType::ASCII) => ("", out1));
}
#[test]
fn attributes_test() {
test!(cell_attributes("\n", FileType::ASCII) => Vec::new());
test!(point_attributes("", FileType::ASCII) => Vec::new());
test!(attributes("\n", FileType::ASCII) => Attributes::new());
let in1 = "CELL_DATA 6\nSCALARS cell_scalars int 1\n0 1 2 3 4 5\n";
let scalar_attrib = Attribute::Scalars {
num_comp: 1,
lookup_table: None,
data: vec![0, 1, 2, 3, 4, 5].into(),
};
let out1 = vec![(String::from("cell_scalars"), scalar_attrib.clone())];
test!(cell_attributes(in1, FileType::ASCII) => out1);
let in2 = "POINT_DATA 6\n SCALARS point_scalars int 1\n0 1 2 3 4 5\n
CELL_DATA 6\n SCALARS cell_scalars int 1\n0 1 2 3 4 5";
let pt_res = vec![(String::from("point_scalars"), scalar_attrib.clone())];
let cl_res = vec![(String::from("cell_scalars"), scalar_attrib)];
let out2 = Attributes {
point: pt_res,
cell: cl_res,
};
test!(attributes(in2, FileType::ASCII) => out2);
}
#[test]
fn dataset_simple_test() {
let in1 = "DATASET UNSTRUCTURED_GRID\nPOINTS 0 float\nCELLS 0 0\nCELL_TYPES 0\n";
let out1 = DataSet::UnstructuredGrid {
points: Vec::<f32>::new().into(),
cells: Cells {
num_cells: 0,
vertices: vec![],
},
cell_types: vec![],
data: Attributes::new(),
};
test!(dataset(in1, FileType::ASCII) => out1);
}
#[test]
fn dataset_test() {
let in1 = "DATASET UNSTRUCTURED_GRID\nPOINTS 3 float\n2 45 2 3 4 1 46 2 0\
CELLS 0 0\nCELL_TYPES 0\n";
let out1 = DataSet::UnstructuredGrid {
points: vec![2.0f32, 45., 2., 3., 4., 1., 46., 2., 0.].into(),
cells: Cells {
num_cells: 0,
vertices: vec![],
},
cell_types: vec![],
data: Attributes::new(),
};
test!(dataset(in1, FileType::ASCII) => out1);
}
}