Skip to content

Commit 2654511

Browse files
committed
Update to nom 8, add test for reading BGEO attributes
1 parent 99cdcc1 commit 2654511

File tree

4 files changed

+120
-81
lines changed

4 files changed

+120
-81
lines changed

Cargo.lock

Lines changed: 19 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

splashsurf_lib/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ rstar = "0.12"
5454
vtkio = { version = "0.6", optional = true }
5555
ply-rs = { version = "0.1.3", optional = true }
5656
flate2 = { version = "1.0", optional = true }
57-
nom = { version = "7.1.3", optional = true }
57+
nom = { version = "8.0", optional = true }
5858
serde_json = { version = "1.0", optional = true }
5959

6060
[dev-dependencies]

splashsurf_lib/src/io/bgeo_format.rs

Lines changed: 99 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -356,20 +356,21 @@ impl AttributeStorage {
356356
mod parser {
357357
use nom::branch::alt;
358358
use nom::bytes::streaming::{tag, take};
359-
use nom::combinator::{map, map_opt, map_res, not, recognize, value, verify};
360-
use nom::multi::count;
359+
use nom::combinator::{map_opt, map_res, not, recognize, value, verify};
360+
use nom::multi::{count, fold};
361361
use nom::number::complete as number;
362362
use nom::{IResult, Parser};
363363

364364
use super::error::{bgeo_error, make_bgeo_error, BgeoParserError, BgeoParserErrorKind};
365365
use super::{AttribDefinition, AttributeStorage, BgeoAttributeType, BgeoFile, BgeoHeader};
366366

367-
pub fn bgeo_parser<'a>() -> impl Parser<&'a [u8], BgeoFile, BgeoParserError<&'a [u8]>> {
367+
pub fn bgeo_parser<'a>(
368+
) -> impl Parser<&'a [u8], Output = BgeoFile, Error = BgeoParserError<&'a [u8]>> {
368369
move |input: &'a [u8]| -> IResult<&'a [u8], BgeoFile, BgeoParserError<&'a [u8]>> {
369370
// Parse file header and attribute definitions
370371
let (input, header) = parse_header(input)?;
371372
let (input, named_attribute_definitions) =
372-
count(parse_attr_def, header.num_point_attrib as usize)(input)?;
373+
count(parse_attr_def, header.num_point_attrib as usize).parse(input)?;
373374

374375
// Add the "position" attribute which should always be present
375376
let special_attribute_definitions = {
@@ -418,12 +419,12 @@ mod parser {
418419

419420
/// Parses the BGEO format magic bytes
420421
fn parse_magic_bytes(input: &[u8]) -> IResult<&[u8], &[u8], BgeoParserError<&[u8]>> {
421-
tag("Bgeo")(input)
422+
tag("Bgeo").parse(input)
422423
}
423424

424425
/// Parses the (unsupported) new BGEO format magic bytes
425426
fn parse_new_magic_bytes(input: &[u8]) -> IResult<&[u8], &[u8], BgeoParserError<&[u8]>> {
426-
tag([0x7f, 0x4e, 0x53, 0x4a])(input)
427+
tag([0x7f, 0x4e, 0x53, 0x4a].as_slice()).parse(input)
427428
}
428429

429430
/// Parses and validates the magic bytes of a BGEO file header
@@ -442,7 +443,8 @@ mod parser {
442443
BgeoParserErrorKind::UnsupportedFormatVersion,
443444
value("".as_bytes(), not(parse_new_magic_bytes)),
444445
)),
445-
))(input)
446+
))
447+
.parse(input)
446448
}
447449

448450
#[test]
@@ -528,7 +530,8 @@ mod parser {
528530
let (input, name_length) = number::be_u16(input)?;
529531
let (input, name) = map_res(take(name_length as usize), |input: &[u8]| {
530532
std::str::from_utf8(input).map_err(|_| BgeoParserErrorKind::InvalidAttributeName)
531-
})(input)?;
533+
})
534+
.parse(input)?;
532535

533536
let (input, size) = number::be_u16(input)?;
534537
let (input, attr_type) = bgeo_error(
@@ -538,7 +541,7 @@ mod parser {
538541

539542
match attr_type {
540543
BgeoAttributeType::Float | BgeoAttributeType::Int | BgeoAttributeType::Vector => {
541-
let (input, default_values) = count(number::be_i32, size as usize)(input)?;
544+
let (input, default_values) = count(number::be_i32, size as usize).parse(input)?;
542545

543546
let attr = AttribDefinition {
544547
name: name.to_string(),
@@ -585,12 +588,12 @@ mod parser {
585588
let mut input = input;
586589

587590
// Get the parser functions
588-
let mut parser_funs: Vec<_> = parsers.iter_mut().map(|p| p.parser()).collect();
591+
//let mut parser_funs: Vec<_> = parsers.iter_mut().map(|p| p.parser()).collect();
589592
// For each point...
590593
for _ in 0..num_points {
591594
// ...apply all parsers in succession
592-
for parser in &mut parser_funs {
593-
let (i, _) = (parser).parse(input)?;
595+
for parser in parsers.iter_mut() {
596+
let (i, _) = parser.parse(input)?;
594597
input = i;
595598
}
596599
}
@@ -682,58 +685,39 @@ mod parser {
682685
Self { attrib, storage }
683686
}
684687

685-
/// Returns a boxed parser for this attribute
686-
fn parser<'a, 'b>(
687-
&'b mut self,
688-
) -> Box<dyn Parser<&'a [u8], (), BgeoParserError<&'a [u8]>> + 'b> {
688+
fn parse<'a>(
689+
&mut self,
690+
input: &'a [u8],
691+
) -> IResult<&'a [u8], (), BgeoParserError<&'a [u8]>> {
689692
match self.attrib.attr_type {
690693
BgeoAttributeType::Int => {
691694
let storage = self.storage.as_int_mut();
692-
let size = self.attrib.size;
693-
Box::new(
694-
move |input: &'a [u8]| -> IResult<&'a [u8], (), BgeoParserError<&'a [u8]>> {
695-
let (input, _) = count(
696-
map(number::be_i32, |val| {
697-
//println!("i32: {}", val);
698-
storage.push(val);
699-
}),
700-
size,
701-
)(input)?;
702-
Ok((input, ()))
703-
},
704-
)
695+
map_res(number::be_i32, |val| {
696+
storage.push(val);
697+
Ok(())
698+
})
699+
.parse(input)
705700
}
706701
BgeoAttributeType::Float => {
707702
let storage = self.storage.as_float_mut();
708-
let size = self.attrib.size;
709-
Box::new(
710-
move |input: &'a [u8]| -> IResult<&'a [u8], (), BgeoParserError<&'a [u8]>> {
711-
let (input, _) = count(
712-
map(number::be_f32, |val| {
713-
//println!("f32: {}", val);
714-
storage.push(val);
715-
}),
716-
size,
717-
)(input)?;
718-
Ok((input, ()))
719-
},
720-
)
703+
map_res(number::be_f32, |val| {
704+
storage.push(val);
705+
Ok(())
706+
})
707+
.parse(input)
721708
}
722709
BgeoAttributeType::Vector => {
723710
let storage = self.storage.as_vec_mut();
724711
let size = self.attrib.size;
725-
Box::new(
726-
move |input: &'a [u8]| -> IResult<&'a [u8], (), BgeoParserError<&'a [u8]>> {
727-
let (input, _) = count(
728-
map(number::be_f32, |val| {
729-
//println!("vec: {}", val);
730-
storage.push(val);
731-
}),
732-
size,
733-
)(input)?;
734-
Ok((input, ()))
712+
fold(
713+
size,
714+
number::be_f32,
715+
|| (),
716+
|_, val| {
717+
storage.push(val);
735718
},
736719
)
720+
.parse(input)
737721
}
738722
_ => panic!("Unsupported attribute type"),
739723
}
@@ -859,7 +843,7 @@ mod error {
859843
mut f: F,
860844
) -> impl FnMut(I) -> IResult<I, O, BgeoParserError<I>>
861845
where
862-
F: Parser<I, O, BgeoParserError<I>>,
846+
F: Parser<I, Output = O, Error = BgeoParserError<I>>,
863847
{
864848
use nom::Err;
865849
move |i: I| match f.parse(i.clone()) {
@@ -888,6 +872,68 @@ fn test_bgeo_read_dam_break() {
888872
assert!(enclosing.contains_aabb(&aabb));
889873
}
890874

875+
#[test]
876+
fn test_bgeo_read_dam_break_attributes() {
877+
let input_file = Path::new("../data/dam_break_frame_9_6859_particles.bgeo");
878+
879+
let bgeo_file = load_bgeo_file(input_file).unwrap();
880+
881+
let particles = particles_from_bgeo_file::<f32>(&bgeo_file).unwrap();
882+
883+
assert_eq!(particles.len(), 6859);
884+
885+
eprintln!("{:?}", bgeo_file.attribute_definitions);
886+
assert_eq!(bgeo_file.attribute_definitions.len(), 3);
887+
assert_eq!(bgeo_file.attribute_data.len(), 3);
888+
889+
use crate::Aabb3d;
890+
let aabb = Aabb3d::from_points(&particles);
891+
let enclosing = Aabb3d::new(
892+
Vector3::new(-2.0, 0.03, -0.8),
893+
Vector3::new(-0.3, 0.7, 0.72),
894+
);
895+
896+
assert!(enclosing.contains_aabb(&aabb));
897+
898+
let attribs = attributes_from_bgeo_file::<f32>(
899+
&bgeo_file,
900+
&[
901+
"id".to_string(),
902+
"density".to_string(),
903+
"velocity".to_string(),
904+
],
905+
)
906+
.unwrap();
907+
908+
assert_eq!(attribs.len(), 3);
909+
910+
assert!(matches!(attribs[0].data, AttributeData::ScalarU64(_)));
911+
assert!(matches!(attribs[1].data, AttributeData::ScalarReal(_)));
912+
assert!(matches!(attribs[2].data, AttributeData::Vector3Real(_)));
913+
914+
if let AttributeData::ScalarU64(ids) = &attribs[0].data {
915+
assert_eq!(ids.len(), particles.len());
916+
assert_eq!(ids[0], 30);
917+
assert_eq!(ids[1], 11);
918+
assert_eq!(ids[2], 12);
919+
}
920+
921+
if let AttributeData::ScalarReal(densities) = &attribs[1].data {
922+
assert_eq!(densities.len(), particles.len());
923+
assert_eq!(densities[0], 1000.1286);
924+
assert_eq!(densities[1], 1001.53424);
925+
assert_eq!(densities[2], 1001.6626);
926+
}
927+
928+
if let AttributeData::Vector3Real(velocities) = &attribs[2].data {
929+
assert_eq!(velocities.len(), particles.len());
930+
assert_eq!(
931+
velocities[0],
932+
Vector3::new(0.3670507, -0.41762838, 0.42659923)
933+
);
934+
}
935+
}
936+
891937
#[test]
892938
fn test_bgeo_write_dam_break() {
893939
let input_file = Path::new("../data/dam_break_frame_9_6859_particles.bgeo");

splashsurf_lib/src/mesh.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ pub struct MeshAttribute<R: Real> {
165165

166166
/// Data of an [`MeshAttribute`] that can be attached to the vertices or cells of a mesh
167167
///
168-
/// One value in the data-set corresponds is associated to a point or cell of the mesh.
168+
/// One value in the data-set is associated to a point or cell of the mesh.
169169
#[derive(Clone, Debug)]
170170
pub enum AttributeData<R: Real> {
171171
ScalarU64(Vec<u64>),

0 commit comments

Comments
 (0)