From 0a2f1210af98396c70cbdb947198e6a3b995879c Mon Sep 17 00:00:00 2001 From: Akhil Velagapudi Date: Sat, 10 Oct 2026 20:28:12 +0000 Subject: [PATCH 1/2] Flatten and parse STEP files in parallel (ENG-3819) strip_flatten and StepFile::parse split their input into chunks and, with the new optional step/rayon feature (enabled by triangulate/parallel), process the chunks on the rayon pool. Results are applied in file order, so the output, duplicate-ID handling and the first reported error match the sequential parse. Without the feature (wasm), each input is one chunk. Parsing also avoids per-record overhead: memchr finds entity names, references parse without nom combinators, UTF-8 is checked once per chunk, reference checks use a bitset, and complex entities use a small vector instead of hash maps. A complex entity that omits a supertype is now an invalid record instead of a panic. --- README.md | 4 +- express/src/gen.rs | 7 +- step/Cargo.toml | 1 + step/src/ap214.rs | 7 +- step/src/parse.rs | 99 ++++---- step/src/step_file.rs | 531 +++++++++++++++++++++++++++++++---------- triangulate/Cargo.toml | 2 +- 7 files changed, 468 insertions(+), 183 deletions(-) diff --git a/README.md b/README.md index d2a6219..a27cda1 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,9 @@ remain visible when the camera moves. - `express`: Parser for EXPRESS schemas files and a matching code generation system - `step`: Auto-generated STEP file parser. This take a _very_ long time to - compile, so it is isolated into this crate. + compile, so it is isolated into this crate. Its optional `rayon` feature + (enabled by `triangulate`'s `parallel` feature) flattens and parses large + files in parallel, with the same result as the sequential build. - `triangulate`: Converts a file loaded by `step` into a triangle mesh, using `cdt` as its core - `nurbs`: A handful of NURBS / B-spline algorithms used by `triangulate` diff --git a/express/src/gen.rs b/express/src/gen.rs index 027874d..b4d31e9 100644 --- a/express/src/gen.rs +++ b/express/src/gen.rs @@ -482,12 +482,13 @@ pub fn gen(s: &mut Syntax) -> Result { use crate::{{ id::{{Id, HasId}}, parse::{{IResult, Logical, Derived, Parse, ParseFromChunks, nom_alt_err, - parse_enum_tag, param_from_chunks, parse_complex_mapping}}, + parse_enum_tag, param_from_chunks, parse_complex_mapping, + take_until_paren}}, step_file::FromEntity, }}; use nom::{{ branch::{{alt}}, - bytes::complete::{{tag, take_until}}, + bytes::complete::tag, character::complete::char, combinator::map, multi::{{many0}}, @@ -509,7 +510,7 @@ pub enum Entity<'a> {{")?; }} impl<'a> ParseFromChunks<'a> for Entity<'a> {{ fn parse_chunks(strs: &[&'a str]) -> IResult<'a, Self> {{ - let (_, r) = take_until("(")(strs[0])?; + let (_, r) = take_until_paren(strs[0])?; match r {{"#)?; for k in &keys { type_map.0[k].write_enum_match(k, &mut buf)?; diff --git a/step/Cargo.toml b/step/Cargo.toml index 1f9b0fa..0a7d42e 100644 --- a/step/Cargo.toml +++ b/step/Cargo.toml @@ -10,6 +10,7 @@ fast-float2 = "0.2.4" log = "0.4.14" memchr = "2.4.0" nom = "7" +rayon = { version = "1.5", optional = true } [dev-dependencies] clap = "2.33" diff --git a/step/src/ap214.rs b/step/src/ap214.rs index 5b14a77..a4bc855 100644 --- a/step/src/ap214.rs +++ b/step/src/ap214.rs @@ -2,12 +2,13 @@ use crate::{ id::{Id, HasId}, parse::{IResult, Logical, Derived, Parse, ParseFromChunks, nom_alt_err, - parse_enum_tag, param_from_chunks, parse_complex_mapping}, + parse_enum_tag, param_from_chunks, parse_complex_mapping, + take_until_paren}, step_file::FromEntity, }; use nom::{ branch::{alt}, - bytes::complete::{tag, take_until}, + bytes::complete::tag, character::complete::char, combinator::map, multi::{many0}, @@ -37043,7 +37044,7 @@ pub enum Entity<'a> { } impl<'a> ParseFromChunks<'a> for Entity<'a> { fn parse_chunks(strs: &[&'a str]) -> IResult<'a, Self> { - let (_, r) = take_until("(")(strs[0])?; + let (_, r) = take_until_paren(strs[0])?; match r { "ABS_FUNCTION" => AbsFunction_::parse_chunks(strs).map(|(s, v)| (s, Entity::AbsFunction(v))), "ACOS_FUNCTION" => AcosFunction_::parse_chunks(strs).map(|(s, v)| (s, Entity::AcosFunction(v))), diff --git a/step/src/parse.rs b/step/src/parse.rs index 912ac29..f19d381 100644 --- a/step/src/parse.rs +++ b/step/src/parse.rs @@ -1,4 +1,3 @@ -use std::collections::{HashSet, HashMap}; use nom::{ branch::{alt}, bytes::complete::tag, @@ -153,14 +152,19 @@ impl<'a> Parse<'a> for bool { } } impl<'a, T> Parse<'a> for Id { + // References are the most common parameter, so this avoids nom's + // combinator overhead; it accepts the same `#digits` and `$` forms. fn parse(s: &str) -> IResult { - alt(( - map_res( - preceded(char('#'), digit1), - |s: &str| s.parse().map(|i| Id::new(i))), + if let Some(rest) = s.strip_prefix('#') { + let n = rest.bytes().take_while(u8::is_ascii_digit).count(); + if let Ok(i) = rest[..n].parse() { + return Ok((&rest[n..], Id::new(i))); + } + } else if let Some(rest) = s.strip_prefix('$') { // NUL id deserializes to 0 - map(char('$'), |_| Id::empty()))) - (s) + return Ok((rest, Id::empty())); + } + nom_alt_err(s) } } @@ -228,36 +232,35 @@ pub(crate) fn parse_enum_tag(s: &str) -> IResult<&str> { //////////////////////////////////////////////////////////////////////////////// -pub(crate) fn parse_entity_decl(s: &[u8]) -> IResult<(usize, Entity)> { - let s = match std::str::from_utf8(s) { - Ok(s) => s, - Err(_) => return nom_err("", ErrorKind::Escaped), // TODO correct code? - }; +/// Returns the text before the first `(`, like nom's `take_until("(")` +/// without building a substring searcher for every entity. +pub(crate) fn take_until_paren(s: &str) -> IResult<'_, &str> { + match memchr(b'(', s.as_bytes()) { + Some(i) => Ok((&s[i..], &s[..i])), + None => nom_err(s, ErrorKind::TakeUntil), + } +} + +pub(crate) fn parse_entity_decl(s: &str) -> IResult<'_, (usize, Entity<'_>)> { map(tuple((Id::<()>::parse, char('='), Entity::parse)), |(i, _, e)| (i.0, e))(s) } -pub(crate) fn parse_entity_fallback(s: &[u8]) -> IResult<(usize, Entity)> { - let s = match std::str::from_utf8(s) { - Ok(s) => s, - Err(_) => return nom_err("", ErrorKind::Escaped), - }; +pub(crate) fn parse_entity_fallback(s: &str) -> IResult<'_, (usize, Entity<'_>)> { map(Id::<()>::parse, |i| (i.0, Entity::_FailedToParse))(s) } pub(crate) fn parse_complex_mapping(s: &str) -> IResult { - // We'll maintain a map from sub-entity name to its argument string, then - // use this map to figure out the tree and construct it. - let mut subentities: HashMap<&str, &str> = HashMap::new(); - - // Map from sub-entity name to the str slice which contains the name plus - // the open parens, used for parsing slices - let mut name_tags: HashMap<&str, &str> = HashMap::new(); + // Sub-entities as (name, name plus open parens, argument string), used + // to figure out the tree and construct it. A repeated name keeps its last + // occurrence. There are only a few parts, so lookups are linear scans. + let mut parts: Vec<(&str, &str, &str)> = Vec::new(); let bstr = s.as_bytes(); let mut depth = 0; let mut index = 0; let mut args_start = 0; let mut name: &str = ""; + let mut name_tag: &str = ""; loop { let next = match memchr3(b'(', b')', b'\'', &bstr[index..]) { Some(i) => i, @@ -271,9 +274,8 @@ pub(crate) fn parse_complex_mapping(s: &str) -> IResult { .expect("Could not convert back to name"); args_start = index + next + 1; let name_tag_slice = &bstr[index..(index + next + 1)]; - let name_tag = std::str::from_utf8(name_tag_slice) + name_tag = std::str::from_utf8(name_tag_slice) .expect("Could not convert tag back to name"); - name_tags.insert(name, name_tag); } depth += 1; }, @@ -283,7 +285,10 @@ pub(crate) fn parse_complex_mapping(s: &str) -> IResult { let arg_slice = &bstr[args_start..(index + next)]; let args = std::str::from_utf8(arg_slice) .expect("Could not convert args"); - subentities.insert(name, args); + match parts.iter_mut().find(|p| p.0 == name) { + Some(p) => *p = (name, name_tag, args), + None => parts.push((name, name_tag, args)), + } } else if depth == 0 { break; } @@ -302,28 +307,24 @@ pub(crate) fn parse_complex_mapping(s: &str) -> IResult { } // Filter out the list of subclasses to those which aren't a parent of // another item in the set; these are our potential leafs. - let mut potential_leafs: HashSet<&str> = subentities.keys() - .map(|i| *i) + let supers: Vec<&[&str]> = parts.iter().map(|p| superclasses_of(p.0)).collect(); + let mut potential_leafs: Vec<(&str, &str)> = parts.iter() + .filter(|p| !supers.iter().any(|s| s.contains(&p.0))) + // Eliminate any leaf with no arguments, since they're just addding + // bonus constraints (which we don't handle anyways) + .filter(|p| p.2 != "") + .map(|p| (p.0, p.1)) .collect(); - for k in subentities.keys() { - for sup in superclasses_of(k) { - potential_leafs.remove(sup); - } - } - // Eliminate any leaf with no arguments, since they're just addding - // bonus constraints (which we don't handle anyways) - potential_leafs.retain(|k| subentities[k] != ""); // Sort potential leafs so that ComplexEntity is deterministic and we can // match against it later - let mut potential_leafs: Vec<&str> = potential_leafs.into_iter().collect(); potential_leafs.sort(); // At this point, we'll build up argument strings by splicing together bits // of arguments from the existing string (to make lifetimes happy), then // parse into leaf entities. let mut leaf_entities = Vec::with_capacity(potential_leafs.len()); - for leaf in potential_leafs.into_iter() { + for (leaf, leaf_tag) in potential_leafs.into_iter() { let mut chain = vec![leaf]; loop { let sup = superclasses_of(chain.last().unwrap()); @@ -333,10 +334,16 @@ pub(crate) fn parse_complex_mapping(s: &str) -> IResult { _ => return nom_err(s, ErrorKind::LengthValue), // TODO: error } } - let mut new_decl: Vec<&str> = vec![name_tags.get(leaf).unwrap()]; + let mut new_decl: Vec<&str> = vec![leaf_tag]; for c in chain.iter().rev() { - if !subentities[c].is_empty() { - new_decl.push(subentities[c]); + // Records are parsed in parallel, so a missing supertype must be + // an error rather than a panic that masks an earlier error. + let args = match parts.iter().find(|p| p.0 == *c) { + Some(p) => p.2, + None => return nom_err(s, ErrorKind::Verify), + }; + if !args.is_empty() { + new_decl.push(args); new_decl.push(if *c == leaf { &")" } else { &"," }); } } @@ -379,9 +386,9 @@ mod tests { #[test] fn test_parse_entity_decl() { - parse_entity_decl(b"#3=SHAPE_DEFINITION_REPRESENTATION(#4,#10);").unwrap(); - parse_entity_decl(b"#38463=ADVANCED_FACE('',(#38464),#38475,.F.);").unwrap(); - parse_entity_decl(b"#395359=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.E-007),#395356,'distance_accuracy_value','confusion accuracy');").unwrap(); - parse_entity_decl(b"#1632=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT(.MILLI.,.METRE.));").unwrap(); + parse_entity_decl("#3=SHAPE_DEFINITION_REPRESENTATION(#4,#10);").unwrap(); + parse_entity_decl("#38463=ADVANCED_FACE('',(#38464),#38475,.F.);").unwrap(); + parse_entity_decl("#395359=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.E-007),#395356,'distance_accuracy_value','confusion accuracy');").unwrap(); + parse_entity_decl("#1632=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT(.MILLI.,.METRE.));").unwrap(); } } diff --git a/step/src/step_file.rs b/step/src/step_file.rs index 0b4d39f..3beef01 100644 --- a/step/src/step_file.rs +++ b/step/src/step_file.rs @@ -1,5 +1,8 @@ use log::warn; -use std::fmt; +use std::{fmt, ops::Range, sync::atomic::{AtomicBool, Ordering}}; + +#[cfg(feature = "rayon")] +use rayon::prelude::*; use crate::{ ap214::Entity, @@ -33,133 +36,190 @@ impl<'a> StepFile<'a> { /// Parses a STEP file from a raw array of bytes /// `data` must be preprocessed by [`strip_flatten`] first pub fn parse(data: &'a [u8]) -> Result { - let blocks = Self::into_blocks(data)?; - if blocks.first().copied() != Some(b"ISO-10303-21;") { + Self::parse_in_chunks(data, BYTES_PER_CHUNK, RECORDS_PER_CHUNK) + } + + /// Parses with the given work sizes, which must not change the result. + fn parse_in_chunks(data: &'a [u8], bytes_per_chunk: usize, records_per_chunk: usize) + -> Result + { + let blocks = Self::into_blocks(data, bytes_per_chunk)?; + let is = |i: usize, text: &[u8]| &data[blocks[i].clone()] == text; + if blocks.is_empty() || !is(0, b"ISO-10303-21;") { return Err(StepParseError::new("missing ISO-10303-21 start marker")); } - let header_start = blocks.iter().position(|b| b == b"HEADER;") + let header_start = (0..blocks.len()).position(|i| is(i, b"HEADER;")) .ok_or_else(|| StepParseError::new("missing HEADER section"))?; - let data_start = blocks.iter() - .position(|b| b == b"DATA;") + let data_start = (0..blocks.len()) + .position(|i| is(i, b"DATA;")) .ok_or_else(|| StepParseError::new("missing DATA section"))? + 1; - if header_start >= data_start - 1 || !blocks[header_start + 1..data_start - 1] - .iter().any(|b| b == b"ENDSEC;") + if header_start >= data_start - 1 || !(header_start + 1..data_start - 1) + .any(|i| is(i, b"ENDSEC;")) { return Err(StepParseError::new("HEADER section missing ENDSEC")); } - let data_end = blocks.iter() - .skip(data_start) - .position(|b| b == b"ENDSEC;") - .map(|i| i + data_start) + let data_end = (data_start..blocks.len()) + .find(|&i| is(i, b"ENDSEC;")) .ok_or_else(|| StepParseError::new("DATA section missing ENDSEC"))?; - if !blocks[data_end + 1..].iter().any(|b| b == b"END-ISO-10303-21;") { + if !(data_end + 1..blocks.len()).any(|i| is(i, b"END-ISO-10303-21;")) { return Err(StepParseError::new("missing END-ISO-10303-21 marker")); } let records = &blocks[data_start..data_end]; - // Size the final ID table from record headers before parsing payloads. - // Malformed headers still receive the normal record error below. - let max_id = records.iter().filter_map(|b| { - let b = b.strip_prefix(b"#")?; - let end = b.iter().position(|c| *c == b'=')?; - std::str::from_utf8(&b[..end]).ok()?.parse::().ok() - }).max().unwrap_or(0); - let mut out: Vec = (0..=max_id).map(|_| Entity::_EmptySlot).collect(); - - for b in records { - let (_, (id, entity)) = parse_entity_decl(*b) - .and_then(|(remaining, value)| { - // Complex entity parsing consumes the full declaration; - // simple entities leave the record terminator. - if remaining.is_empty() || remaining == ";" { - Ok((remaining, value)) - } else { - Err(nom::Err::Error(nom::error::Error::new( - remaining, nom::error::ErrorKind::Eof))) - } - }) - .or_else(|e| { - warn!("Failed to parse {}: {:?}", - std::str::from_utf8(b).unwrap_or("[INVALID UTF-8]"), - e); - parse_entity_fallback(*b).and_then(|(remaining, value)| { - if is_fallback_entity_record(remaining) { - Ok((remaining, value)) - } else { - Err(nom::Err::Error(nom::error::Error::new( - remaining, nom::error::ErrorKind::Eof))) - } - }) - }) - .map_err(|_| StepParseError::new(format!( - "invalid DATA record: {}", - String::from_utf8_lossy(b))))?; - out[id] = entity; + let chunks: Vec<_> = records.chunks(records_per_chunk).collect(); + // Records are adjacent, so one UTF-8 check usually covers a chunk. + let texts = map_in_order(chunks.len(), 1, |c| { + let c = chunks[c]; + std::str::from_utf8(&data[c[0].start..c[c.len() - 1].end]).ok() + }); + let parse_nth = |r: usize| { + let (c, range) = (r / records_per_chunk, &records[r]); + let text = match texts[c] { + Some(text) => { + let base = chunks[c][0].start; + Some(&text[range.start - base..range.end - base]) + } + None => std::str::from_utf8(&data[range.clone()]).ok(), + }; + text.and_then(|s| parse_record(s).ok()).map(|(_, (_, entity))| entity) + }; + + // Size the ID table from record headers and map each ID to its last + // record, which a sequential parse would have kept. A header that + // does not parse belongs to an invalid record, reported below. + let ids: Vec> = map_in_order(chunks.len(), 1, |c| { + chunks[c].iter().map(|r| record_id(&data[r.clone()])).collect::>() + }).into_iter().flatten().collect(); + let max_id = ids.iter().flatten().copied().max().unwrap_or(0); + let mut record_of = vec![NO_RECORD; max_id + 1]; + for (r, id) in ids.iter().enumerate() { + if let Some(id) = *id { + record_of[id] = r; + } + } + + // Parse each ID's record straight into its slot, in parallel. Records + // shadowed by a later duplicate are parsed only to detect errors. + let failed = AtomicBool::new(false); + let out: Vec = map_in_order(max_id + 1, records_per_chunk, |id| match record_of[id] { + NO_RECORD => Entity::_EmptySlot, + r => parse_nth(r).unwrap_or_else(|| { + failed.store(true, Ordering::Relaxed); + Entity::_EmptySlot + }), + }); + if failed.into_inner() || ids.iter().enumerate().any(|(r, id)| match *id { + Some(id) => record_of[id] != r && parse_nth(r).is_none(), + None => true, + }) { + let first = map_in_order(chunks.len(), 1, |c| { + let start = c * records_per_chunk; + (start..start + chunks[c].len()).find(|&r| parse_nth(r).is_none()) + }); + let r = first.into_iter().flatten().next().expect("an invalid record"); + return Err(StepParseError::new(format!( + "invalid DATA record: {}", + String::from_utf8_lossy(&data[records[r].clone()])))); + } + + // One bit per ID keeps reference lookups in cache. + let mut defined = vec![0u64; max_id / 64 + 1]; + for id in (0..=max_id).filter(|&id| record_of[id] != NO_RECORD) { + defined[id / 64] |= 1 << (id % 64); + } + let errors = map_in_order(chunks.len(), 1, |c| chunks[c].iter() + .find_map(|r| check_references(&data[r.clone()], &defined))); + if let Some(e) = errors.into_iter().flatten().next() { + return Err(e); } - validate_references(records, &out)?; Ok(Self(out)) } /// Flattens a STEP file, removing comments and whitespace pub fn strip_flatten(data: &[u8]) -> Result, StepParseError> { - let mut out = Vec::with_capacity(data.len()); - let mut i = 0; - let mut in_string = false; - while i < data.len() { - // Copy ordinary text in runs instead of growing/checking the - // output for every byte. Only lexical boundaries need state. - let length = data[i..].iter().position(|c| *c == b'\'' || !c.is_ascii() - || (!in_string && (*c == b'/' || c.is_ascii_whitespace()))) - .unwrap_or(data.len() - i); - out.extend_from_slice(&data[i..i + length]); - i += length; - if i == data.len() { break; } - if !in_string && data[i..].starts_with(b"/*") { - let length = memchr::memmem::find(&data[i + 2..], b"*/") - .ok_or_else(|| StepParseError::new("unterminated comment"))?; - i += length + 4; - continue; - } + Self::flatten_in_chunks(data, BYTES_PER_CHUNK) + } - let c = data[i]; - if c == b'\'' { - out.push(c); - // Escaped quotes toggle twice with no bytes between them. - in_string = !in_string; - } else if !in_string && c.is_ascii_whitespace() { - // Whitespace is insignificant outside literals. - } else if !c.is_ascii() { - // Preserve the established lossy policy for legacy encoded - // files while ensuring the borrowed parser receives UTF-8. - out.push(b'?'); - } else { - out.push(c); + /// Flattens with the given work size, which must not change the result. + fn flatten_in_chunks(data: &[u8], bytes_per_chunk: usize) -> Result, StepParseError> { + // Chunks end after a newline, so no `/*` or `*/` spans two chunks. + // Each chunk is flattened as if it starts in code; a chunk that + // actually starts inside a literal or comment is flattened again. + let mut chunks = Vec::new(); + let mut start = 0; + while start < data.len() { + let end = match start.checked_add(bytes_per_chunk) { + Some(target) if target < data.len() => memchr::memchr(b'\n', &data[target..]) + .map_or(data.len(), |i| target + i + 1), + _ => data.len(), + }; + chunks.push(start..end); + start = end; + } + let mut flat = map_in_order(chunks.len(), 1, + |c| flatten_chunk(&data[chunks[c].clone()], Lexical::Code)); + let mut state = Lexical::Code; + for (r, chunk) in chunks.iter().zip(&mut flat) { + if state != Lexical::Code { + *chunk = flatten_chunk(&data[r.clone()], state); } - i += 1; + state = chunk.1; } - if in_string { - Err(StepParseError::new("unterminated string literal")) - } else { - Ok(out) + match state { + Lexical::Comment => Err(StepParseError::new("unterminated comment")), + Lexical::Literal => Err(StepParseError::new("unterminated string literal")), + Lexical::Code if flat.len() <= 1 => Ok(flat.pop().map(|(f, _)| f).unwrap_or_default()), + Lexical::Code => { + let mut out = vec![0; flat.iter().map(|(f, _)| f.len()).sum()]; + let mut dst = Vec::with_capacity(flat.len()); + let mut rest = &mut out[..]; + for (f, _) in &flat { + let (head, tail) = rest.split_at_mut(f.len()); + dst.push(head); + rest = tail; + } + #[cfg(feature = "rayon")] + dst.into_par_iter().zip(&flat).for_each(|(d, (f, _))| d.copy_from_slice(f)); + #[cfg(not(feature = "rayon"))] + dst.into_iter().zip(&flat).for_each(|(d, (f, _))| d.copy_from_slice(f)); + Ok(out) + } } } - /// Splits a STEP file into individual blocks. The input must be pre-processed - /// by [`strip_flatten`] beforehand. - fn into_blocks(data: &[u8]) -> Result, StepParseError> { - let mut blocks = Vec::new(); + /// Splits a STEP file into individual blocks, returned as byte ranges. + /// The input must be pre-processed by [`strip_flatten`] beforehand. + fn into_blocks(data: &[u8], bytes_per_chunk: usize) -> Result>, StepParseError> { + // A semicolon ends a block unless an odd number of quotes precede it + // (doubled quotes toggle twice). Each chunk records its semicolons by + // the parity of the quotes before them within the chunk, so chunks + // are scanned independently and joined by parity. + let chunks: Vec<_> = (0..data.len()).step_by(bytes_per_chunk) + .map(|start| start..data.len().min(start.saturating_add(bytes_per_chunk))) + .collect(); + let scanned = map_in_order(chunks.len(), 1, |c| { + let r = &chunks[c]; + let mut semicolons = [Vec::new(), Vec::new()]; + let mut odd = false; + for i in memchr::memchr2_iter(b'\'', b';', &data[r.clone()]) { + if data[r.start + i] == b'\'' { + odd = !odd; + } else { + semicolons[odd as usize].push(r.start + i); + } + } + (semicolons, odd) + }); + let mut blocks = Vec::with_capacity(scanned.iter().map(|(s, _)| s[0].len()).sum()); let mut start = 0; let mut in_string = false; - // Doubled quotes toggle twice, preserving literal state without - // treating delimiters inside strings as record boundaries. - for i in memchr::memchr2_iter(b'\'', b';', data) { - if data[i] == b'\'' { - in_string = !in_string; - } else if !in_string { - blocks.push(&data[start..=i]); + for (semicolons, odd) in scanned { + for i in &semicolons[in_string as usize] { + blocks.push(start..i + 1); start = i + 1; } + in_string ^= odd; } if in_string { return Err(StepParseError::new("unterminated string literal")); @@ -175,42 +235,200 @@ impl<'a> StepFile<'a> { } } -/// Checks explicit entity references in the original records. This is kept -/// separate from `Entity::upstream`, because `$` is represented internally as -/// ID 0 and fallback entities do not expose their parameters there. -fn validate_references( - blocks: &[&[u8]], - entities: &[Entity], -) -> Result<(), StepParseError> { - for block in blocks { - let equals = block.iter().position(|c| *c == b'=').expect("parsed DATA declaration"); - let mut in_string = false; - for offset in memchr::memchr2_iter(b'\'', b'#', &block[equals + 1..]) { - let i = equals + 1 + offset; - if block[i] == b'\'' { - in_string = !in_string; - } else if !in_string { - let start = i + 1; - let mut end = start; - while block.get(end).map_or(false, u8::is_ascii_digit) { - end += 1; +/// Input bytes per parallel flattening or block-splitting task. Without +/// `rayon` the whole file is one chunk, which is the sequential algorithm. +const BYTES_PER_CHUNK: usize = if cfg!(feature = "rayon") { 1 << 20 } else { usize::MAX }; +/// DATA records per parallel parsing or validation task. +const RECORDS_PER_CHUNK: usize = if cfg!(feature = "rayon") { 4096 } else { usize::MAX }; + +/// Marks an ID that no DATA record declares. +const NO_RECORD: usize = usize::MAX; + +/// Returns `[f(0), f(1), ..., f(n - 1)]`. With the `rayon` feature, tasks of +/// at least `min_len` items run in parallel; smaller inputs stay on the +/// calling thread. +fn map_in_order(n: usize, min_len: usize, f: impl Fn(usize) -> R + Sync + Send) -> Vec { + #[cfg(feature = "rayon")] + if n > min_len { + return (0..n).into_par_iter().with_min_len(min_len).map(f).collect(); + } + (0..n).map(f).collect() +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +enum Lexical { + Code, + Literal, + Comment, +} + +/// Byte classes for [`flatten_chunk`] outside literals and comments. +const DROP: u8 = 0; +const KEEP: u8 = 1; +const SPECIAL: u8 = 2; +const CODE_CLASS: [u8; 256] = { + let mut class = [KEEP; 256]; + // Whitespace (as in `u8::is_ascii_whitespace`) is insignificant + // outside literals. + class[b' ' as usize] = DROP; + class[b'\t' as usize] = DROP; + class[b'\n' as usize] = DROP; + class[b'\x0C' as usize] = DROP; + class[b'\r' as usize] = DROP; + class[b'\'' as usize] = SPECIAL; + class[b'/' as usize] = SPECIAL; + let mut c = 0x80; + while c < 256 { + class[c] = SPECIAL; + c += 1; + } + class +}; + +/// Returns `data` without comments, and without whitespace outside literals, +/// starting in `state`, and the state at the end of `data`. +fn flatten_chunk(data: &[u8], mut state: Lexical) -> (Vec, Lexical) { + // Output never exceeds input, so write at `j` into a sized buffer. + let mut out = vec![0; data.len()]; + let mut j = 0; + let mut i = 0; + while i < data.len() { + match state { + Lexical::Comment => match memchr::memmem::find(&data[i..], b"*/") { + Some(n) => { + i += n + 2; + state = Lexical::Code; + } + None => break, + }, + Lexical::Code => { + // Copy blocks without whitespace or special bytes at once; + // otherwise copy bytes, dropping whitespace without branches. + 'code: while i < data.len() { + let block = &data[i..data.len().min(i + 16)]; + if block.len() == 16 && block.iter().fold(true, |all, &c| + all & (c > b' ') & (c < 0x80) & (c != b'\'') & (c != b'/')) + { + out[j..j + 16].copy_from_slice(block); + i += 16; + j += 16; + continue; + } + for &c in block { + let class = CODE_CLASS[c as usize]; + if class == SPECIAL { + break 'code; + } + out[j] = c; + j += class as usize; + i += 1; + } } - if end > start { - let target_text = std::str::from_utf8(&block[start..end]).unwrap(); - let target = target_text.parse::().ok(); - if target.map_or(true, |target| { - matches!(entities.get(target), None | Some(Entity::_EmptySlot)) - }) { - return Err(StepParseError::new(format!( - "entity {} references undefined entity #{}", - String::from_utf8_lossy(&block[..equals]), target_text - ))); + let Some(&c) = data.get(i) else { break }; + i += 1; + if c == b'/' && data.get(i) == Some(&b'*') { + i += 1; + state = Lexical::Comment; + continue; + } + out[j] = match c { + b'\'' => { + state = Lexical::Literal; + c } + b'/' => c, + // Preserve the established lossy policy for legacy + // encoded files while ensuring the borrowed parser + // receives UTF-8. + _ => b'?', + }; + j += 1; + } + Lexical::Literal => { + let n = data[i..].iter().position(|c| *c == b'\'' || !c.is_ascii()) + .unwrap_or(data.len() - i); + out[j..j + n].copy_from_slice(&data[i..i + n]); + i += n; + j += n; + if let Some(&c) = data.get(i) { + i += 1; + if c == b'\'' { + // Escaped quotes toggle twice with no bytes between them. + out[j] = c; + state = Lexical::Code; + } else { + out[j] = b'?'; + } + j += 1; } } } } - Ok(()) + out.truncate(j); + (out, state) +} + +fn parse_record(s: &str) -> crate::parse::IResult<'_, (usize, Entity<'_>)> { + parse_entity_decl(s) + .and_then(|(remaining, value)| { + // Complex entity parsing consumes the full declaration; + // simple entities leave the record terminator. + if remaining.is_empty() || remaining == ";" { + Ok((remaining, value)) + } else { + Err(nom::Err::Error(nom::error::Error::new( + remaining, nom::error::ErrorKind::Eof))) + } + }) + .or_else(|e| { + warn!("Failed to parse {}: {:?}", s, e); + parse_entity_fallback(s).and_then(|(remaining, value)| { + if is_fallback_entity_record(remaining) { + Ok((remaining, value)) + } else { + Err(nom::Err::Error(nom::error::Error::new( + remaining, nom::error::ErrorKind::Eof))) + } + }) + }) +} + +/// Reads the ID from a record's `#ID=` header. +fn record_id(b: &[u8]) -> Option { + let b = b.strip_prefix(b"#")?; + let end = b.iter().position(|c| *c == b'=')?; + std::str::from_utf8(&b[..end]).ok()?.parse::().ok() +} + +/// Checks explicit entity references in an original record. This is kept +/// separate from `Entity::upstream`, because `$` is represented internally as +/// ID 0 and fallback entities do not expose their parameters there. +fn check_references(block: &[u8], defined: &[u64]) -> Option { + let equals = block.iter().position(|c| *c == b'=').expect("parsed DATA declaration"); + let mut in_string = false; + for offset in memchr::memchr2_iter(b'\'', b'#', &block[equals + 1..]) { + let i = equals + 1 + offset; + if block[i] == b'\'' { + in_string = !in_string; + } else if !in_string { + let start = i + 1; + let mut end = start; + while block.get(end).map_or(false, u8::is_ascii_digit) { + end += 1; + } + if end > start { + let target_text = std::str::from_utf8(&block[start..end]).unwrap(); + let target = target_text.parse::().ok(); + if !target.map_or(false, |t| defined.get(t / 64).map_or(false, |w| w >> (t % 64) & 1 == 1)) { + return Some(StepParseError::new(format!( + "entity {} references undefined entity #{}", + String::from_utf8_lossy(&block[..equals]), target_text + ))); + } + } + } + } + None } fn is_fallback_entity_record(s: &str) -> bool { @@ -269,6 +487,9 @@ mod tests { .contains("missing DATA")); assert!(StepFile::strip_flatten(b"/* never closed").unwrap_err().to_string() .contains("unterminated comment")); + // SI_UNIT is a NAMED_UNIT, which this complex entity omits. + assert!(parse_data("#1=(LENGTH_UNIT()SI_UNIT(.MILLI.,.METRE.));").unwrap_err() + .to_string().contains("invalid DATA record")); } #[test] @@ -302,6 +523,58 @@ mod tests { assert!(explicit_zero.contains("#7 references undefined entity #0")); } + #[test] + fn chunk_sizes_do_not_change_results() { + // A literal and a comment span lines and hold delimiters. IDs are out + // of order and #3 repeats, so its last record must win. + let text = b"ISO-10303-21;\r\nHEADER;/* a ' quote\n; and */ENDSEC;\nDATA;\n\ + #3=CARTESIAN_POINT('first',(0.,0.,0.));\n\ + #2 = VERTEX_POINT ( 'it''s; /* not a\ncomment */', #3 ) ;\n\ + #1=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT(.MILLI.,.METRE.));\n\ + #3=CARTESIAN_POINT('caf\xc3\xa9',(1.,2.,3.));\n\ + #9=NOT_IN_AP214('x');\nENDSEC;\nEND-ISO-10303-21;\n"; + let flat = StepFile::flatten_in_chunks(text, usize::MAX).unwrap(); + let flat_text = std::str::from_utf8(&flat).unwrap(); + assert!(flat_text.starts_with("ISO-10303-21;HEADER;ENDSEC;DATA;#3=")); + assert!(flat_text.contains("#2=VERTEX_POINT('it''s; /* not a\ncomment */',#3);")); + assert!(flat_text.contains("#3=CARTESIAN_POINT('caf??',(1.,2.,3.));")); + let step = StepFile::parse_in_chunks(&flat, usize::MAX, usize::MAX).unwrap(); + let point = step.entity::(Id::new(3)).unwrap(); + assert_eq!(point.coordinates.iter().map(|c| c.0).collect::>(), [1., 2., 3.]); + assert_eq!(step.0.len(), 10); + let entities = format!("{:?}", step); + + for bytes in 1..=text.len() { + assert_eq!(StepFile::flatten_in_chunks(text, bytes).unwrap(), flat); + for records in 1..=6 { + let step = StepFile::parse_in_chunks(&flat, bytes, records).unwrap(); + assert_eq!(format!("{:?}", step), entities); + } + } + } + + #[test] + fn chunked_parsing_reports_the_first_error_in_file_order() { + // Both invalid records are shadowed by later duplicate IDs. + let invalid = b"ISO-10303-21;HEADER;ENDSEC;DATA;#1=lowercase(1);#2=NOT_IN_AP214(#1);\ + #1=NOT_IN_AP214(1);#3=lowercase(3);#3=NOT_IN_AP214(3);ENDSEC;END-ISO-10303-21;"; + let undefined = b"ISO-10303-21;HEADER;ENDSEC;DATA;#1=NOT_IN_AP214(1);\ + #2=NOT_IN_AP214(#8);#3=NOT_IN_AP214(#9);ENDSEC;END-ISO-10303-21;"; + for bytes in 1..=invalid.len() { + for records in 1..=4 { + let e = StepFile::parse_in_chunks(invalid, bytes, records).unwrap_err(); + assert_eq!(e.to_string(), "STEP parse error: invalid DATA record: #1=lowercase(1);"); + let e = StepFile::parse_in_chunks(undefined, bytes, records).unwrap_err(); + assert!(e.to_string().ends_with("#2 references undefined entity #8")); + } + } + let unterminated = b"#1=A('x\n;');\n/* open\n#2=B('y');\n"; + for bytes in 1..=unterminated.len() { + assert!(StepFile::flatten_in_chunks(unterminated, bytes).unwrap_err().to_string() + .contains("unterminated comment")); + } + } + #[test] fn reference_validation_handles_literals_forward_refs_nulls_and_fallbacks() { parse_data( diff --git a/triangulate/Cargo.toml b/triangulate/Cargo.toml index 6865c70..7df3dbb 100644 --- a/triangulate/Cargo.toml +++ b/triangulate/Cargo.toml @@ -17,7 +17,7 @@ thiserror = "2" serde = { version = "1", features = ["derive"] } [features] -parallel = ["rayon"] +parallel = ["rayon", "step/rayon"] profiling = [] [dev-dependencies] From 750783812fbcf7094b82fa9c9fdf23eec0bb7022 Mon Sep 17 00:00:00 2001 From: Akhil Velagapudi Date: Sat, 10 Oct 2026 21:53:20 +0000 Subject: [PATCH 2/2] Simplify parallel STEP parsing and shrink Entity to 64 bytes StepFile::parse now takes &str and strip_flatten returns String, since flattening already emits only ASCII. This removes the UTF-8 checks and fallbacks from parsing. Records are parsed in chunks and applied in file order, as in the sequential loop. This removes the ID-to-record table, the duplicate-ID and first-error bookkeeping, and the error rescan, with the same result. The generator now boxes entities by estimated payload size instead of attribute count. The 110 records with payloads over 56 bytes are boxed, so every Entity slot is 64 bytes instead of 128, and a compile-time assertion keeps it so. --- express/src/gen.rs | 97 ++++++++-- step/src/ap214.rs | 414 +++++++++++++++++++++--------------------- step/src/parse.rs | 12 +- step/src/step_file.rs | 170 +++++++---------- 4 files changed, 358 insertions(+), 335 deletions(-) diff --git a/express/src/gen.rs b/express/src/gen.rs index b4d31e9..7c8982b 100644 --- a/express/src/gen.rs +++ b/express/src/gen.rs @@ -96,32 +96,101 @@ impl <'a> TypeMap<'a> { } } -impl<'a> Type<'a> { - fn boxed_entity(&self) -> bool { - // Large schema records must not inflate every slot in the entity table. - // Keep the common point, placement and topology records inline. - matches!(self, Type::Entity { attrs, .. } if attrs.len() > 8) +/// Entities with larger estimated payloads are boxed, so that every slot in +/// the entity table is 64 bytes: the payload plus the enum tag. +const MAX_INLINE_ENTITY: usize = 56; + +/// Estimated layout of a generated Rust type. +#[derive(Clone, Copy)] +struct Layout { + size: usize, + align: usize, + /// Whether a spare bit pattern can represent `None` + niche: bool, +} +const ID_LAYOUT: Layout = Layout { size: 8, align: 8, niche: false }; + +fn round_up(n: usize, align: usize) -> usize { + (n + align - 1) / align * align +} + +impl<'a> TypeMap<'a> { + /// Estimates the layout of generated type `t`. `named` maps camel-case + /// type names back to schema names. + fn layout(&self, t: &str, named: &HashMap) -> Layout { + if let Some(inner) = t.strip_prefix("Option<").and_then(|t| t.strip_suffix('>')) { + let l = self.layout(inner, named); + let size = if l.niche { l.size } else { round_up(l.size + 1, l.align) }; + return Layout { size, align: l.align, niche: false }; + } + if let Some(inner) = t.strip_prefix("ArrayVec::<").and_then(|t| t.strip_suffix('>')) { + let (item, cap) = inner.rsplit_once(", ").unwrap(); + let l = self.layout(item, named); + let align = l.align.max(4); + let size = round_up(l.size * cap.parse::().unwrap() + 4, align); + return Layout { size, align, niche: false }; + } + if t.starts_with("Vec<") { + return Layout { size: 24, align: 8, niche: true }; + } + match t { + "&'a str" => return Layout { size: 16, align: 8, niche: true }, + "bool" | "Logical" => return Layout { size: 1, align: 1, niche: true }, + "f64" | "i64" | "usize" => return Layout { size: 8, align: 8, niche: false }, + _ => (), + } + let name = named[t.trim_end_matches("<'a>")]; + match &self.0[name] { + Type::Entity { .. } => ID_LAYOUT, + Type::Select(_) if self.is_entity(name) => ID_LAYOUT, + Type::Select(variants) => { + let ls: Vec = variants.iter() + .map(|v| self.layout(&self.to_rtype(v), named)) + .collect(); + let size = ls.iter().map(|l| l.size).max().unwrap(); + let align = ls.iter().map(|l| l.align).max().unwrap(); + // With one data variant, the unused variant fits in a niche. + let size = if ls.len() == 1 && ls[0].niche { size } else { round_up(size + 1, align) }; + Layout { size, align, niche: true } + } + Type::Enum(_) => Layout { size: 1, align: 1, niche: true }, + Type::Redeclared(c) => self.layout(&self.to_rtype(c), named), + Type::RedeclaredPrimitive(c) | Type::Primitive(c) => self.layout(c, named), + Type::Aggregation { .. } => self.layout(&self.to_rtype(name), named), + } } - fn write_enum_variant(&self, name: &str, buf: &mut W) -> std::fmt::Result + /// Whether entity `name` is boxed in the `Entity` enum + fn boxed_entity(&self, name: &str, named: &HashMap) -> bool { + let Type::Entity { attrs, .. } = &self.0[name] else { return false }; + let fields: Vec = attrs.iter().filter(|a| !a.derived).map(|a| self.layout( + &if a.optional { format!("Option<{}>", a.type_) } else { a.type_.clone() }, + named)).collect(); + let align = fields.iter().map(|l| l.align).max().unwrap_or(1); + round_up(fields.iter().map(|l| l.size).sum(), align) > MAX_INLINE_ENTITY + } +} + +impl<'a> Type<'a> { + fn write_enum_variant(&self, name: &str, boxed: bool, buf: &mut W) -> std::fmt::Result where W: std::fmt::Write { match self { Type::Entity{..} => { let payload = format!("{}_<'a>", to_camel(name)); writeln!(buf, " {}({}),", to_camel(name), - if self.boxed_entity() { format!("Box<{}>", payload) } else { payload }) + if boxed { format!("Box<{}>", payload) } else { payload }) }, _ => Ok(()), } } - fn write_enum_match(&self, name: &str, buf: &mut W) -> std::fmt::Result + fn write_enum_match(&self, name: &str, boxed: bool, buf: &mut W) -> std::fmt::Result where W: std::fmt::Write { match self { Type::Entity{..} => writeln!(buf, r#" "{0}" => {1}_::parse_chunks(strs).map(|(s, v)| (s, Entity::{1}({2}))),"#, - capitalize(name), to_camel(name), if self.boxed_entity() { "Box::new(v)" } else { "v" }), + capitalize(name), to_camel(name), if boxed { "Box::new(v)" } else { "v" }), _ => Ok(()), } } @@ -499,21 +568,27 @@ use arrayvec::ArrayVec;")?; for k in &keys { type_map.0[k].write_type(k, &mut buf, &type_map)?; } + let named: HashMap = keys.iter().map(|k| (to_camel(k), *k)).collect(); + let boxed: HashSet<&str> = keys.iter().copied() + .filter(|k| type_map.boxed_entity(k, &named)) + .collect(); writeln!(&mut buf, "#[derive(Debug)] pub enum Entity<'a> {{")?; for k in &keys { - type_map.0[k].write_enum_variant(k, &mut buf)?; + type_map.0[k].write_enum_variant(k, boxed.contains(k), &mut buf)?; } writeln!(&mut buf, r#" ComplexEntity(Vec>), _FailedToParse, _EmptySlot, }} +// Keep entity table slots small; see MAX_INLINE_ENTITY in the generator. +const _: () = assert!(std::mem::size_of::() <= 64); impl<'a> ParseFromChunks<'a> for Entity<'a> {{ fn parse_chunks(strs: &[&'a str]) -> IResult<'a, Self> {{ let (_, r) = take_until_paren(strs[0])?; match r {{"#)?; for k in &keys { - type_map.0[k].write_enum_match(k, &mut buf)?; + type_map.0[k].write_enum_match(k, boxed.contains(k), &mut buf)?; } writeln!(&mut buf, r#" "" => parse_complex_mapping(strs[0]), _ => nom_alt_err(r), diff --git a/step/src/ap214.rs b/step/src/ap214.rs index a4bc855..95347fe 100644 --- a/step/src/ap214.rs +++ b/step/src/ap214.rs @@ -36127,8 +36127,8 @@ pub enum Entity<'a> { AcosFunction(AcosFunction_<'a>), Action(Action_<'a>), ActionAssignment(ActionAssignment_<'a>), - ActionDirective(ActionDirective_<'a>), - ActionMethod(ActionMethod_<'a>), + ActionDirective(Box>), + ActionMethod(Box>), ActionMethodRelationship(ActionMethodRelationship_<'a>), ActionProperty(ActionProperty_<'a>), ActionPropertyRepresentation(ActionPropertyRepresentation_<'a>), @@ -36136,28 +36136,28 @@ pub enum Entity<'a> { ActionRequestAssignment(ActionRequestAssignment_<'a>), ActionRequestSolution(ActionRequestSolution_<'a>), ActionRequestStatus(ActionRequestStatus_<'a>), - ActionResource(ActionResource_<'a>), - ActionResourceRequirement(ActionResourceRequirement_<'a>), + ActionResource(Box>), + ActionResourceRequirement(Box>), ActionResourceType(ActionResourceType_<'a>), ActionStatus(ActionStatus_<'a>), Address(Box>), AdvancedBrepShapeRepresentation(AdvancedBrepShapeRepresentation_<'a>), AdvancedFace(AdvancedFace_<'a>), - AlternateProductRelationship(AlternateProductRelationship_<'a>), + AlternateProductRelationship(Box>), AmountOfSubstanceMeasureWithUnit(AmountOfSubstanceMeasureWithUnit_<'a>), AmountOfSubstanceUnit(AmountOfSubstanceUnit_<'a>), AndExpression(AndExpression_<'a>), AngularDimension(AngularDimension_<'a>), AngularLocation(AngularLocation_<'a>), AngularSize(AngularSize_<'a>), - AngularityTolerance(AngularityTolerance_<'a>), + AngularityTolerance(Box>), AnnotationCurveOccurrence(AnnotationCurveOccurrence_<'a>), AnnotationFillArea(AnnotationFillArea_<'a>), AnnotationFillAreaOccurrence(AnnotationFillAreaOccurrence_<'a>), AnnotationOccurrence(AnnotationOccurrence_<'a>), AnnotationOccurrenceAssociativity(AnnotationOccurrenceAssociativity_<'a>), AnnotationOccurrenceRelationship(AnnotationOccurrenceRelationship_<'a>), - AnnotationPlane(AnnotationPlane_<'a>), + AnnotationPlane(Box>), AnnotationSubfigureOccurrence(AnnotationSubfigureOccurrence_<'a>), AnnotationSymbol(AnnotationSymbol_<'a>), AnnotationSymbolOccurrence(AnnotationSymbolOccurrence_<'a>), @@ -36207,7 +36207,7 @@ pub enum Entity<'a> { AreaMeasureWithUnit(AreaMeasureWithUnit_<'a>), AreaUnit(AreaUnit_<'a>), AsinFunction(AsinFunction_<'a>), - AssemblyComponentUsage(AssemblyComponentUsage_<'a>), + AssemblyComponentUsage(Box>), AssemblyComponentUsageSubstitute(AssemblyComponentUsageSubstitute_<'a>), AtanFunction(AtanFunction_<'a>), AttributeClassificationAssignment(AttributeClassificationAssignment_<'a>), @@ -36219,14 +36219,14 @@ pub enum Entity<'a> { Axis2Placement3d(Axis2Placement3d_<'a>), BSplineCurve(BSplineCurve_<'a>), BSplineCurveWithKnots(Box>), - BSplineSurface(BSplineSurface_<'a>), + BSplineSurface(Box>), BSplineSurfaceWithKnots(Box>), BackgroundColour(BackgroundColour_<'a>), BarringHole(BarringHole_<'a>), Bead(Bead_<'a>), BeadEnd(BeadEnd_<'a>), BezierCurve(BezierCurve_<'a>), - BezierSurface(BezierSurface_<'a>), + BezierSurface(Box>), BinaryBooleanExpression(BinaryBooleanExpression_<'a>), BinaryFunctionCall(BinaryFunctionCall_<'a>), BinaryGenericExpression(BinaryGenericExpression_<'a>), @@ -36257,9 +36257,9 @@ pub enum Entity<'a> { CameraModelD3WithHlhsr(CameraModelD3WithHlhsr_<'a>), CameraUsage(CameraUsage_<'a>), CartesianPoint(CartesianPoint_<'a>), - CartesianTransformationOperator(CartesianTransformationOperator_<'a>), - CartesianTransformationOperator2d(CartesianTransformationOperator2d_<'a>), - CartesianTransformationOperator3d(CartesianTransformationOperator3d_<'a>), + CartesianTransformationOperator(Box>), + CartesianTransformationOperator2d(Box>), + CartesianTransformationOperator3d(Box>), CelsiusTemperatureMeasureWithUnit(CelsiusTemperatureMeasureWithUnit_<'a>), CentreOfSymmetry(CentreOfSymmetry_<'a>), Certification(Certification_<'a>), @@ -36267,13 +36267,13 @@ pub enum Entity<'a> { CertificationType(CertificationType_<'a>), Chamfer(Chamfer_<'a>), ChamferOffset(ChamferOffset_<'a>), - CharacterGlyphSymbol(CharacterGlyphSymbol_<'a>), - CharacterizedClass(CharacterizedClass_<'a>), + CharacterGlyphSymbol(Box>), + CharacterizedClass(Box>), CharacterizedObject(CharacterizedObject_<'a>), Circle(Circle_<'a>), CircularClosedProfile(CircularClosedProfile_<'a>), CircularPattern(CircularPattern_<'a>), - CircularRunoutTolerance(CircularRunoutTolerance_<'a>), + CircularRunoutTolerance(Box>), Class(Class_<'a>), ClassSystem(ClassSystem_<'a>), ClassUsageEffectivityContextAssignment(ClassUsageEffectivityContextAssignment_<'a>), @@ -36281,11 +36281,11 @@ pub enum Entity<'a> { ClassificationRole(ClassificationRole_<'a>), ClosedPathProfile(ClosedPathProfile_<'a>), ClosedShell(ClosedShell_<'a>), - CoaxialityTolerance(CoaxialityTolerance_<'a>), + CoaxialityTolerance(Box>), Colour(Colour_<'a>), ColourRgb(ColourRgb_<'a>), ColourSpecification(ColourSpecification_<'a>), - CommonDatum(CommonDatum_<'a>), + CommonDatum(Box>), ComparisonEqual(ComparisonEqual_<'a>), ComparisonExpression(ComparisonExpression_<'a>), ComparisonGreater(ComparisonGreater_<'a>), @@ -36299,24 +36299,24 @@ pub enum Entity<'a> { CompositeHole(CompositeHole_<'a>), CompositeShapeAspect(CompositeShapeAspect_<'a>), CompositeText(CompositeText_<'a>), - CompositeTextWithAssociatedCurves(CompositeTextWithAssociatedCurves_<'a>), + CompositeTextWithAssociatedCurves(Box>), CompositeTextWithBlankingBox(CompositeTextWithBlankingBox_<'a>), CompositeTextWithExtent(CompositeTextWithExtent_<'a>), CompoundFeature(CompoundFeature_<'a>), CompoundRepresentationItem(CompoundRepresentationItem_<'a>), CompoundShapeRepresentation(CompoundShapeRepresentation_<'a>), ConcatExpression(ConcatExpression_<'a>), - ConcentricityTolerance(ConcentricityTolerance_<'a>), + ConcentricityTolerance(Box>), ConceptFeatureOperator(ConceptFeatureOperator_<'a>), ConceptFeatureRelationship(ConceptFeatureRelationship_<'a>), ConceptFeatureRelationshipWithCondition(ConceptFeatureRelationshipWithCondition_<'a>), ConditionalConceptFeature(ConditionalConceptFeature_<'a>), - ConfigurableItem(ConfigurableItem_<'a>), + ConfigurableItem(Box>), ConfigurationDefinition(ConfigurationDefinition_<'a>), ConfigurationDesign(ConfigurationDesign_<'a>), ConfigurationEffectivity(ConfigurationEffectivity_<'a>), ConfigurationInterpolation(ConfigurationInterpolation_<'a>), - ConfigurationItem(ConfigurationItem_<'a>), + ConfigurationItem(Box>), ConfiguredEffectivityAssignment(ConfiguredEffectivityAssignment_<'a>), ConfiguredEffectivityContextAssignment(ConfiguredEffectivityContextAssignment_<'a>), Conic(Conic_<'a>), @@ -36328,7 +36328,7 @@ pub enum Entity<'a> { ConstructiveGeometryRepresentationRelationship(ConstructiveGeometryRepresentationRelationship_<'a>), ContactRatioRepresentation(ContactRatioRepresentation_<'a>), ContextDependentInvisibility(ContextDependentInvisibility_<'a>), - ContextDependentOverRidingStyledItem(ContextDependentOverRidingStyledItem_<'a>), + ContextDependentOverRidingStyledItem(Box>), ContextDependentShapeRepresentation(ContextDependentShapeRepresentation_<'a>), ContextDependentUnit(ContextDependentUnit_<'a>), Contract(Contract_<'a>), @@ -36349,7 +36349,7 @@ pub enum Entity<'a> { CurveStyleRendering(CurveStyleRendering_<'a>), CurveSweptSolidShapeRepresentation(CurveSweptSolidShapeRepresentation_<'a>), CylindricalPair(CylindricalPair_<'a>), - CylindricalPairRange(CylindricalPairRange_<'a>), + CylindricalPairRange(Box>), CylindricalPairValue(CylindricalPairValue_<'a>), CylindricalSurface(CylindricalSurface_<'a>), CylindricityTolerance(CylindricityTolerance_<'a>), @@ -36361,11 +36361,11 @@ pub enum Entity<'a> { DateRole(DateRole_<'a>), DateTimeRole(DateTimeRole_<'a>), DatedEffectivity(DatedEffectivity_<'a>), - Datum(Datum_<'a>), + Datum(Box>), DatumFeature(DatumFeature_<'a>), DatumFeatureCallout(DatumFeatureCallout_<'a>), DatumReference(DatumReference_<'a>), - DatumTarget(DatumTarget_<'a>), + DatumTarget(Box>), DatumTargetCallout(DatumTargetCallout_<'a>), DefaultToleranceTable(DefaultToleranceTable_<'a>), DefaultToleranceTableCell(DefaultToleranceTableCell_<'a>), @@ -36387,10 +36387,10 @@ pub enum Entity<'a> { DimensionCalloutRelationship(DimensionCalloutRelationship_<'a>), DimensionCurve(DimensionCurve_<'a>), DimensionCurveDirectedCallout(DimensionCurveDirectedCallout_<'a>), - DimensionCurveTerminator(DimensionCurveTerminator_<'a>), + DimensionCurveTerminator(Box>), DimensionPair(DimensionPair_<'a>), DimensionRelatedToleranceZoneElement(DimensionRelatedToleranceZoneElement_<'a>), - DimensionTextAssociativity(DimensionTextAssociativity_<'a>), + DimensionTextAssociativity(Box>), DimensionalCharacteristicRepresentation(DimensionalCharacteristicRepresentation_<'a>), DimensionalExponents(DimensionalExponents_<'a>), DimensionalLocation(DimensionalLocation_<'a>), @@ -36404,7 +36404,7 @@ pub enum Entity<'a> { DirectionShapeRepresentation(DirectionShapeRepresentation_<'a>), DivExpression(DivExpression_<'a>), Document(Document_<'a>), - DocumentFile(DocumentFile_<'a>), + DocumentFile(Box>), DocumentProductAssociation(DocumentProductAssociation_<'a>), DocumentProductEquivalence(DocumentProductEquivalence_<'a>), DocumentReference(DocumentReference_<'a>), @@ -36426,13 +36426,13 @@ pub enum Entity<'a> { DraughtingSpecificationReference(DraughtingSpecificationReference_<'a>), DraughtingSubfigureRepresentation(DraughtingSubfigureRepresentation_<'a>), DraughtingSymbolRepresentation(DraughtingSymbolRepresentation_<'a>), - DraughtingTextLiteralWithDelineation(DraughtingTextLiteralWithDelineation_<'a>), + DraughtingTextLiteralWithDelineation(Box>), DraughtingTitle(DraughtingTitle_<'a>), DrawingDefinition(DrawingDefinition_<'a>), DrawingRevision(DrawingRevision_<'a>), DrawingRevisionSequence(DrawingRevisionSequence_<'a>), DrawingSheetLayout(DrawingSheetLayout_<'a>), - DrawingSheetRevision(DrawingSheetRevision_<'a>), + DrawingSheetRevision(Box>), DrawingSheetRevisionUsage(DrawingSheetRevisionUsage_<'a>), Edge(Edge_<'a>), EdgeBasedWireframeModel(EdgeBasedWireframeModel_<'a>), @@ -36471,7 +36471,7 @@ pub enum Entity<'a> { ExternallyDefinedCurveFont(ExternallyDefinedCurveFont_<'a>), ExternallyDefinedDimensionDefinition(ExternallyDefinedDimensionDefinition_<'a>), ExternallyDefinedFeatureDefinition(ExternallyDefinedFeatureDefinition_<'a>), - ExternallyDefinedGeneralProperty(ExternallyDefinedGeneralProperty_<'a>), + ExternallyDefinedGeneralProperty(Box>), ExternallyDefinedHatchStyle(ExternallyDefinedHatchStyle_<'a>), ExternallyDefinedItem(ExternallyDefinedItem_<'a>), ExternallyDefinedItemRelationship(ExternallyDefinedItemRelationship_<'a>), @@ -36528,7 +36528,7 @@ pub enum Entity<'a> { GeometricSet(GeometricSet_<'a>), GeometricTolerance(GeometricTolerance_<'a>), GeometricToleranceRelationship(GeometricToleranceRelationship_<'a>), - GeometricToleranceWithDatumReference(GeometricToleranceWithDatumReference_<'a>), + GeometricToleranceWithDatumReference(Box>), GeometricToleranceWithDefinedUnit(GeometricToleranceWithDefinedUnit_<'a>), GeometricalToleranceCallout(GeometricalToleranceCallout_<'a>), GeometricallyBounded2dWireframeRepresentation(GeometricallyBounded2dWireframeRepresentation_<'a>), @@ -36541,10 +36541,10 @@ pub enum Entity<'a> { GroupRelationship(GroupRelationship_<'a>), HalfSpaceSolid(HalfSpaceSolid_<'a>), HardnessRepresentation(HardnessRepresentation_<'a>), - HiddenElementOverRidingStyledItem(HiddenElementOverRidingStyledItem_<'a>), + HiddenElementOverRidingStyledItem(Box>), HoleBottom(HoleBottom_<'a>), HoleInPanel(HoleInPanel_<'a>), - HomokineticPair(HomokineticPair_<'a>), + HomokineticPair(Box>), Hyperbola(Hyperbola_<'a>), IdAttribute(IdAttribute_<'a>), IdentificationAssignment(IdentificationAssignment_<'a>), @@ -36552,7 +36552,7 @@ pub enum Entity<'a> { InclusionProductConceptFeature(InclusionProductConceptFeature_<'a>), IndexExpression(IndexExpression_<'a>), InitialState(InitialState_<'a>), - InstancedFeature(InstancedFeature_<'a>), + InstancedFeature(Box>), IntLiteral(IntLiteral_<'a>), IntNumericVariable(IntNumericVariable_<'a>), IntValueFunction(IntValueFunction_<'a>), @@ -36596,9 +36596,9 @@ pub enum Entity<'a> { LightSourceAmbient(LightSourceAmbient_<'a>), LightSourceDirectional(LightSourceDirectional_<'a>), LightSourcePositional(LightSourcePositional_<'a>), - LightSourceSpot(LightSourceSpot_<'a>), + LightSourceSpot(Box>), LikeExpression(LikeExpression_<'a>), - LimitsAndFits(LimitsAndFits_<'a>), + LimitsAndFits(Box>), Line(Line_<'a>), LineProfileTolerance(LineProfileTolerance_<'a>), LinearDimension(LinearDimension_<'a>), @@ -36613,7 +36613,7 @@ pub enum Entity<'a> { LotEffectivity(LotEffectivity_<'a>), LuminousIntensityMeasureWithUnit(LuminousIntensityMeasureWithUnit_<'a>), LuminousIntensityUnit(LuminousIntensityUnit_<'a>), - MakeFromUsageOption(MakeFromUsageOption_<'a>), + MakeFromUsageOption(Box>), ManifoldSolidBrep(ManifoldSolidBrep_<'a>), ManifoldSubsurfaceShapeRepresentation(ManifoldSubsurfaceShapeRepresentation_<'a>), ManifoldSurfaceShapeRepresentation(ManifoldSurfaceShapeRepresentation_<'a>), @@ -36625,7 +36625,7 @@ pub enum Entity<'a> { MaterialProperty(MaterialProperty_<'a>), MaterialPropertyRepresentation(MaterialPropertyRepresentation_<'a>), MaximumFunction(MaximumFunction_<'a>), - MeasureQualification(MeasureQualification_<'a>), + MeasureQualification(Box>), MeasureRepresentationItem(MeasureRepresentationItem_<'a>), MeasureWithUnit(MeasureWithUnit_<'a>), MechanicalDesignGeometricPresentationArea(MechanicalDesignGeometricPresentationArea_<'a>), @@ -36641,7 +36641,7 @@ pub enum Entity<'a> { MomentsOfInertiaRepresentation(MomentsOfInertiaRepresentation_<'a>), MotionLinkRelationship(MotionLinkRelationship_<'a>), MultExpression(MultExpression_<'a>), - MultiLanguageAttributeAssignment(MultiLanguageAttributeAssignment_<'a>), + MultiLanguageAttributeAssignment(Box>), MultipleArityBooleanExpression(MultipleArityBooleanExpression_<'a>), MultipleArityFunctionCall(MultipleArityFunctionCall_<'a>), MultipleArityGenericExpression(MultipleArityGenericExpression_<'a>), @@ -36650,7 +36650,7 @@ pub enum Entity<'a> { NameAttribute(NameAttribute_<'a>), NamedUnit(NamedUnit_<'a>), NamedUnitVariable(NamedUnitVariable_<'a>), - NextAssemblyUsageOccurrence(NextAssemblyUsageOccurrence_<'a>), + NextAssemblyUsageOccurrence(Box>), NgonClosedProfile(NgonClosedProfile_<'a>), NonManifoldSurfaceShapeRepresentation(NonManifoldSurfaceShapeRepresentation_<'a>), NotExpression(NotExpression_<'a>), @@ -36689,7 +36689,7 @@ pub enum Entity<'a> { PairValue(PairValue_<'a>), Parabola(Parabola_<'a>), ParallelOffset(ParallelOffset_<'a>), - ParallelismTolerance(ParallelismTolerance_<'a>), + ParallelismTolerance(Box>), ParametricRepresentationContext(ParametricRepresentationContext_<'a>), PartialCircularProfile(PartialCircularProfile_<'a>), Path(Path_<'a>), @@ -36699,23 +36699,23 @@ pub enum Entity<'a> { PatternOmitMembership(PatternOmitMembership_<'a>), Pcurve(Pcurve_<'a>), PerpendicularTo(PerpendicularTo_<'a>), - PerpendicularityTolerance(PerpendicularityTolerance_<'a>), - Person(Person_<'a>), + PerpendicularityTolerance(Box>), + Person(Box>), PersonAndOrganization(PersonAndOrganization_<'a>), PersonAndOrganizationAddress(Box>), PersonAndOrganizationAssignment(PersonAndOrganizationAssignment_<'a>), PersonAndOrganizationRole(PersonAndOrganizationRole_<'a>), PersonalAddress(Box>), - PhysicallyModelledProductDefinition(PhysicallyModelledProductDefinition_<'a>), - PlacedDatumTargetFeature(PlacedDatumTargetFeature_<'a>), + PhysicallyModelledProductDefinition(Box>), + PlacedDatumTargetFeature(Box>), PlacedFeature(PlacedFeature_<'a>), Placement(Placement_<'a>), PlanarBox(PlanarBox_<'a>), - PlanarCurvePair(PlanarCurvePair_<'a>), + PlanarCurvePair(Box>), PlanarCurvePairRange(PlanarCurvePairRange_<'a>), PlanarExtent(PlanarExtent_<'a>), PlanarPair(PlanarPair_<'a>), - PlanarPairRange(PlanarPairRange_<'a>), + PlanarPairRange(Box>), PlanarPairValue(PlanarPairValue_<'a>), PlanarShapeRepresentation(PlanarShapeRepresentation_<'a>), Plane(Plane_<'a>), @@ -36727,16 +36727,16 @@ pub enum Entity<'a> { PocketBottom(PocketBottom_<'a>), Point(Point_<'a>), PointOnCurve(PointOnCurve_<'a>), - PointOnPlanarCurvePair(PointOnPlanarCurvePair_<'a>), - PointOnPlanarCurvePairRange(PointOnPlanarCurvePairRange_<'a>), + PointOnPlanarCurvePair(Box>), + PointOnPlanarCurvePairRange(Box>), PointOnPlanarCurvePairValue(PointOnPlanarCurvePairValue_<'a>), PointOnSurface(PointOnSurface_<'a>), - PointOnSurfacePair(PointOnSurfacePair_<'a>), - PointOnSurfacePairRange(PointOnSurfacePairRange_<'a>), + PointOnSurfacePair(Box>), + PointOnSurfacePairRange(Box>), PointOnSurfacePairValue(PointOnSurfacePairValue_<'a>), PointPlacementShapeRepresentation(PointPlacementShapeRepresentation_<'a>), PointReplica(PointReplica_<'a>), - PointStyle(PointStyle_<'a>), + PointStyle(Box>), PolyLoop(PolyLoop_<'a>), Polyline(Polyline_<'a>), PositionTolerance(PositionTolerance_<'a>), @@ -36767,14 +36767,14 @@ pub enum Entity<'a> { PrismaticPair(PrismaticPair_<'a>), PrismaticPairRange(PrismaticPairRange_<'a>), PrismaticPairValue(PrismaticPairValue_<'a>), - ProcessOperation(ProcessOperation_<'a>), + ProcessOperation(Box>), ProcessPlan(ProcessPlan_<'a>), ProcessProductAssociation(ProcessProductAssociation_<'a>), ProcessPropertyAssociation(ProcessPropertyAssociation_<'a>), - Product(Product_<'a>), + Product(Box>), ProductCategory(ProductCategory_<'a>), ProductCategoryRelationship(ProductCategoryRelationship_<'a>), - ProductClass(ProductClass_<'a>), + ProductClass(Box>), ProductConcept(ProductConcept_<'a>), ProductConceptContext(ProductConceptContext_<'a>), ProductConceptFeature(ProductConceptFeature_<'a>), @@ -36789,40 +36789,40 @@ pub enum Entity<'a> { ProductDefinitionContextRole(ProductDefinitionContextRole_<'a>), ProductDefinitionEffectivity(ProductDefinitionEffectivity_<'a>), ProductDefinitionFormation(ProductDefinitionFormation_<'a>), - ProductDefinitionFormationRelationship(ProductDefinitionFormationRelationship_<'a>), + ProductDefinitionFormationRelationship(Box>), ProductDefinitionFormationWithSpecifiedSource(ProductDefinitionFormationWithSpecifiedSource_<'a>), ProductDefinitionOccurrenceRelationship(ProductDefinitionOccurrenceRelationship_<'a>), ProductDefinitionProcess(ProductDefinitionProcess_<'a>), - ProductDefinitionRelationship(ProductDefinitionRelationship_<'a>), - ProductDefinitionResource(ProductDefinitionResource_<'a>), + ProductDefinitionRelationship(Box>), + ProductDefinitionResource(Box>), ProductDefinitionShape(ProductDefinitionShape_<'a>), ProductDefinitionSubstitute(ProductDefinitionSubstitute_<'a>), - ProductDefinitionUsage(ProductDefinitionUsage_<'a>), - ProductDefinitionWithAssociatedDocuments(ProductDefinitionWithAssociatedDocuments_<'a>), - ProductIdentification(ProductIdentification_<'a>), + ProductDefinitionUsage(Box>), + ProductDefinitionWithAssociatedDocuments(Box>), + ProductIdentification(Box>), ProductProcessPlan(ProductProcessPlan_<'a>), ProductRelatedProductCategory(ProductRelatedProductCategory_<'a>), - ProductSpecification(ProductSpecification_<'a>), + ProductSpecification(Box>), ProjectedZoneDefinition(ProjectedZoneDefinition_<'a>), ProjectionCurve(ProjectionCurve_<'a>), ProjectionDirectedCallout(ProjectionDirectedCallout_<'a>), - PromissoryUsageOccurrence(PromissoryUsageOccurrence_<'a>), + PromissoryUsageOccurrence(Box>), PropertyDefinition(PropertyDefinition_<'a>), PropertyDefinitionRelationship(PropertyDefinitionRelationship_<'a>), PropertyDefinitionRepresentation(PropertyDefinitionRepresentation_<'a>), PropertyProcess(PropertyProcess_<'a>), QualifiedRepresentationItem(QualifiedRepresentationItem_<'a>), QualitativeUncertainty(QualitativeUncertainty_<'a>), - QuantifiedAssemblyComponentUsage(QuantifiedAssemblyComponentUsage_<'a>), + QuantifiedAssemblyComponentUsage(Box>), QuasiUniformCurve(QuasiUniformCurve_<'a>), - QuasiUniformSurface(QuasiUniformSurface_<'a>), - RackAndPinionPair(RackAndPinionPair_<'a>), + QuasiUniformSurface(Box>), + RackAndPinionPair(Box>), RackAndPinionPairRange(RackAndPinionPairRange_<'a>), RackAndPinionPairValue(RackAndPinionPairValue_<'a>), RadiusDimension(RadiusDimension_<'a>), RatioMeasureWithUnit(RatioMeasureWithUnit_<'a>), RatioUnit(RatioUnit_<'a>), - RationalBSplineCurve(RationalBSplineCurve_<'a>), + RationalBSplineCurve(Box>), RationalBSplineSurface(Box>), RealDefinedFunction(RealDefinedFunction_<'a>), RealLiteral(RealLiteral_<'a>), @@ -36830,9 +36830,9 @@ pub enum Entity<'a> { RectangularClosedProfile(RectangularClosedProfile_<'a>), RectangularCompositeSurface(RectangularCompositeSurface_<'a>), RectangularPattern(RectangularPattern_<'a>), - RectangularTrimmedSurface(RectangularTrimmedSurface_<'a>), + RectangularTrimmedSurface(Box>), ReferencedModifiedDatum(ReferencedModifiedDatum_<'a>), - RelativeEventOccurrence(RelativeEventOccurrence_<'a>), + RelativeEventOccurrence(Box>), RepItemGroup(RepItemGroup_<'a>), ReparametrisedCompositeCurveSegment(ReparametrisedCompositeCurveSegment_<'a>), ReplicateFeature(ReplicateFeature_<'a>), @@ -36842,11 +36842,11 @@ pub enum Entity<'a> { RepresentationMap(RepresentationMap_<'a>), RepresentationRelationship(RepresentationRelationship_<'a>), RepresentationRelationshipWithTransformation(RepresentationRelationshipWithTransformation_<'a>), - RequirementForActionResource(RequirementForActionResource_<'a>), + RequirementForActionResource(Box>), ResourceProperty(ResourceProperty_<'a>), ResourcePropertyRepresentation(ResourcePropertyRepresentation_<'a>), ResourceRequirementType(ResourceRequirementType_<'a>), - ResultingPath(ResultingPath_<'a>), + ResultingPath(Box>), Retention(Retention_<'a>), RevolutePair(RevolutePair_<'a>), RevolutePairRange(RevolutePairRange_<'a>), @@ -36858,9 +36858,9 @@ pub enum Entity<'a> { RightCircularCone(RightCircularCone_<'a>), RightCircularCylinder(RightCircularCylinder_<'a>), RoleAssociation(RoleAssociation_<'a>), - RollingCurvePair(RollingCurvePair_<'a>), + RollingCurvePair(Box>), RollingCurvePairValue(RollingCurvePairValue_<'a>), - RollingSurfacePair(RollingSurfacePair_<'a>), + RollingSurfacePair(Box>), RollingSurfacePairValue(RollingSurfacePairValue_<'a>), RotationAboutDirection(RotationAboutDirection_<'a>), RoundHole(RoundHole_<'a>), @@ -36870,7 +36870,7 @@ pub enum Entity<'a> { RunoutZoneDefinition(RunoutZoneDefinition_<'a>), RunoutZoneOrientation(RunoutZoneOrientation_<'a>), RunoutZoneOrientationReferenceDirection(RunoutZoneOrientationReferenceDirection_<'a>), - ScrewPair(ScrewPair_<'a>), + ScrewPair(Box>), ScrewPairRange(ScrewPairRange_<'a>), ScrewPairValue(ScrewPairValue_<'a>), SeamCurve(SeamCurve_<'a>), @@ -36899,9 +36899,9 @@ pub enum Entity<'a> { SimpleStringExpression(SimpleStringExpression_<'a>), SinFunction(SinFunction_<'a>), SlashExpression(SlashExpression_<'a>), - SlidingCurvePair(SlidingCurvePair_<'a>), + SlidingCurvePair(Box>), SlidingCurvePairValue(SlidingCurvePairValue_<'a>), - SlidingSurfacePair(SlidingSurfacePair_<'a>), + SlidingSurfacePair(Box>), SlidingSurfacePairValue(SlidingSurfacePairValue_<'a>), Slot(Slot_<'a>), SlotEnd(SlotEnd_<'a>), @@ -36909,10 +36909,10 @@ pub enum Entity<'a> { SolidAngleUnit(SolidAngleUnit_<'a>), SolidModel(SolidModel_<'a>), SolidReplica(SolidReplica_<'a>), - SpecifiedHigherUsageOccurrence(SpecifiedHigherUsageOccurrence_<'a>), + SpecifiedHigherUsageOccurrence(Box>), Sphere(Sphere_<'a>), SphericalPair(SphericalPair_<'a>), - SphericalPairRange(SphericalPairRange_<'a>), + SphericalPairRange(Box>), SphericalPairValue(SphericalPairValue_<'a>), SphericalSurface(SphericalSurface_<'a>), SqlMappableDefinedFunction(SqlMappableDefinedFunction_<'a>), @@ -36935,13 +36935,13 @@ pub enum Entity<'a> { SurfaceCurveSweptAreaSolid(SurfaceCurveSweptAreaSolid_<'a>), SurfaceOfLinearExtrusion(SurfaceOfLinearExtrusion_<'a>), SurfaceOfRevolution(SurfaceOfRevolution_<'a>), - SurfacePair(SurfacePair_<'a>), + SurfacePair(Box>), SurfacePairRange(SurfacePairRange_<'a>), SurfacePatch(SurfacePatch_<'a>), SurfaceProfileTolerance(SurfaceProfileTolerance_<'a>), SurfaceRenderingProperties(SurfaceRenderingProperties_<'a>), SurfaceReplica(SurfaceReplica_<'a>), - SurfaceSideStyle(SurfaceSideStyle_<'a>), + SurfaceSideStyle(Box>), SurfaceStyleBoundary(SurfaceStyleBoundary_<'a>), SurfaceStyleControlGrid(SurfaceStyleControlGrid_<'a>), SurfaceStyleFillArea(SurfaceStyleFillArea_<'a>), @@ -36957,7 +36957,7 @@ pub enum Entity<'a> { SurfaceStyleUsage(SurfaceStyleUsage_<'a>), SurfaceTextureRepresentation(SurfaceTextureRepresentation_<'a>), SweptAreaSolid(SweptAreaSolid_<'a>), - SweptDiskSolid(SweptDiskSolid_<'a>), + SweptDiskSolid(Box>), SweptFaceSolid(SweptFaceSolid_<'a>), SweptSurface(SweptSurface_<'a>), SymbolColour(SymbolColour_<'a>), @@ -36966,22 +36966,22 @@ pub enum Entity<'a> { SymbolStyle(SymbolStyle_<'a>), SymbolTarget(SymbolTarget_<'a>), SymmetricShapeAspect(SymmetricShapeAspect_<'a>), - SymmetryTolerance(SymmetryTolerance_<'a>), + SymmetryTolerance(Box>), TactileAppearanceRepresentation(TactileAppearanceRepresentation_<'a>), TanFunction(TanFunction_<'a>), Tangent(Tangent_<'a>), Taper(Taper_<'a>), TeeProfile(TeeProfile_<'a>), TerminatorSymbol(TerminatorSymbol_<'a>), - TextLiteral(TextLiteral_<'a>), - TextLiteralWithAssociatedCurves(TextLiteralWithAssociatedCurves_<'a>), - TextLiteralWithBlankingBox(TextLiteralWithBlankingBox_<'a>), - TextLiteralWithDelineation(TextLiteralWithDelineation_<'a>), - TextLiteralWithExtent(TextLiteralWithExtent_<'a>), + TextLiteral(Box>), + TextLiteralWithAssociatedCurves(Box>), + TextLiteralWithBlankingBox(Box>), + TextLiteralWithDelineation(Box>), + TextLiteralWithExtent(Box>), TextStringRepresentation(TextStringRepresentation_<'a>), TextStyle(TextStyle_<'a>), TextStyleForDefinedFont(TextStyleForDefinedFont_<'a>), - TextStyleWithBoxCharacteristics(TextStyleWithBoxCharacteristics_<'a>), + TextStyleWithBoxCharacteristics(Box>), TextStyleWithMirror(TextStyleWithMirror_<'a>), TextStyleWithSpacing(TextStyleWithSpacing_<'a>), ThermodynamicTemperatureMeasureWithUnit(ThermodynamicTemperatureMeasureWithUnit_<'a>), @@ -36991,34 +36991,34 @@ pub enum Entity<'a> { TimeIntervalAssignment(TimeIntervalAssignment_<'a>), TimeIntervalBasedEffectivity(TimeIntervalBasedEffectivity_<'a>), TimeIntervalRole(TimeIntervalRole_<'a>), - TimeIntervalWithBounds(TimeIntervalWithBounds_<'a>), + TimeIntervalWithBounds(Box>), TimeMeasureWithUnit(TimeMeasureWithUnit_<'a>), TimeUnit(TimeUnit_<'a>), ToleranceValue(ToleranceValue_<'a>), - ToleranceZone(ToleranceZone_<'a>), + ToleranceZone(Box>), ToleranceZoneDefinition(ToleranceZoneDefinition_<'a>), ToleranceZoneForm(ToleranceZoneForm_<'a>), TopologicalRepresentationItem(TopologicalRepresentationItem_<'a>), ToroidalSurface(ToroidalSurface_<'a>), Torus(Torus_<'a>), - TotalRunoutTolerance(TotalRunoutTolerance_<'a>), + TotalRunoutTolerance(Box>), TransitionFeature(TransitionFeature_<'a>), - TrimmedCurve(TrimmedCurve_<'a>), + TrimmedCurve(Box>), TwoDirectionRepeatFactor(TwoDirectionRepeatFactor_<'a>), TypeQualifier(TypeQualifier_<'a>), UnaryBooleanExpression(UnaryBooleanExpression_<'a>), UnaryFunctionCall(UnaryFunctionCall_<'a>), UnaryGenericExpression(UnaryGenericExpression_<'a>), UnaryNumericExpression(UnaryNumericExpression_<'a>), - UncertaintyAssignedRepresentation(UncertaintyAssignedRepresentation_<'a>), - UncertaintyMeasureWithUnit(UncertaintyMeasureWithUnit_<'a>), + UncertaintyAssignedRepresentation(Box>), + UncertaintyMeasureWithUnit(Box>), UncertaintyQualifier(UncertaintyQualifier_<'a>), UnconstrainedPair(UnconstrainedPair_<'a>), UnconstrainedPairValue(UnconstrainedPairValue_<'a>), UniformCurve(UniformCurve_<'a>), - UniformSurface(UniformSurface_<'a>), - UniversalPair(UniversalPair_<'a>), - UniversalPairRange(UniversalPairRange_<'a>), + UniformSurface(Box>), + UniversalPair(Box>), + UniversalPairRange(Box>), UniversalPairValue(UniversalPairValue_<'a>), ValueFunction(ValueFunction_<'a>), ValueRange(ValueRange_<'a>), @@ -37026,14 +37026,14 @@ pub enum Entity<'a> { Variable(Variable_<'a>), VariableSemantics(VariableSemantics_<'a>), Vector(Vector_<'a>), - VectorStyle(VectorStyle_<'a>), + VectorStyle(Box>), VeeProfile(VeeProfile_<'a>), - VersionedActionRequest(VersionedActionRequest_<'a>), - VersionedActionRequestRelationship(VersionedActionRequestRelationship_<'a>), + VersionedActionRequest(Box>), + VersionedActionRequestRelationship(Box>), Vertex(Vertex_<'a>), VertexLoop(VertexLoop_<'a>), VertexPoint(VertexPoint_<'a>), - ViewVolume(Box>), + ViewVolume(ViewVolume_<'a>), VisualAppearanceRepresentation(VisualAppearanceRepresentation_<'a>), VolumeMeasureWithUnit(VolumeMeasureWithUnit_<'a>), VolumeUnit(VolumeUnit_<'a>), @@ -37042,6 +37042,8 @@ pub enum Entity<'a> { _FailedToParse, _EmptySlot, } +// Keep entity table slots small; see MAX_INLINE_ENTITY in the generator. +const _: () = assert!(std::mem::size_of::() <= 64); impl<'a> ParseFromChunks<'a> for Entity<'a> { fn parse_chunks(strs: &[&'a str]) -> IResult<'a, Self> { let (_, r) = take_until_paren(strs[0])?; @@ -37050,8 +37052,8 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "ACOS_FUNCTION" => AcosFunction_::parse_chunks(strs).map(|(s, v)| (s, Entity::AcosFunction(v))), "ACTION" => Action_::parse_chunks(strs).map(|(s, v)| (s, Entity::Action(v))), "ACTION_ASSIGNMENT" => ActionAssignment_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionAssignment(v))), - "ACTION_DIRECTIVE" => ActionDirective_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionDirective(v))), - "ACTION_METHOD" => ActionMethod_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionMethod(v))), + "ACTION_DIRECTIVE" => ActionDirective_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionDirective(Box::new(v)))), + "ACTION_METHOD" => ActionMethod_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionMethod(Box::new(v)))), "ACTION_METHOD_RELATIONSHIP" => ActionMethodRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionMethodRelationship(v))), "ACTION_PROPERTY" => ActionProperty_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionProperty(v))), "ACTION_PROPERTY_REPRESENTATION" => ActionPropertyRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionPropertyRepresentation(v))), @@ -37059,28 +37061,28 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "ACTION_REQUEST_ASSIGNMENT" => ActionRequestAssignment_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionRequestAssignment(v))), "ACTION_REQUEST_SOLUTION" => ActionRequestSolution_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionRequestSolution(v))), "ACTION_REQUEST_STATUS" => ActionRequestStatus_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionRequestStatus(v))), - "ACTION_RESOURCE" => ActionResource_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionResource(v))), - "ACTION_RESOURCE_REQUIREMENT" => ActionResourceRequirement_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionResourceRequirement(v))), + "ACTION_RESOURCE" => ActionResource_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionResource(Box::new(v)))), + "ACTION_RESOURCE_REQUIREMENT" => ActionResourceRequirement_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionResourceRequirement(Box::new(v)))), "ACTION_RESOURCE_TYPE" => ActionResourceType_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionResourceType(v))), "ACTION_STATUS" => ActionStatus_::parse_chunks(strs).map(|(s, v)| (s, Entity::ActionStatus(v))), "ADDRESS" => Address_::parse_chunks(strs).map(|(s, v)| (s, Entity::Address(Box::new(v)))), "ADVANCED_BREP_SHAPE_REPRESENTATION" => AdvancedBrepShapeRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::AdvancedBrepShapeRepresentation(v))), "ADVANCED_FACE" => AdvancedFace_::parse_chunks(strs).map(|(s, v)| (s, Entity::AdvancedFace(v))), - "ALTERNATE_PRODUCT_RELATIONSHIP" => AlternateProductRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::AlternateProductRelationship(v))), + "ALTERNATE_PRODUCT_RELATIONSHIP" => AlternateProductRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::AlternateProductRelationship(Box::new(v)))), "AMOUNT_OF_SUBSTANCE_MEASURE_WITH_UNIT" => AmountOfSubstanceMeasureWithUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::AmountOfSubstanceMeasureWithUnit(v))), "AMOUNT_OF_SUBSTANCE_UNIT" => AmountOfSubstanceUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::AmountOfSubstanceUnit(v))), "AND_EXPRESSION" => AndExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::AndExpression(v))), "ANGULAR_DIMENSION" => AngularDimension_::parse_chunks(strs).map(|(s, v)| (s, Entity::AngularDimension(v))), "ANGULAR_LOCATION" => AngularLocation_::parse_chunks(strs).map(|(s, v)| (s, Entity::AngularLocation(v))), "ANGULAR_SIZE" => AngularSize_::parse_chunks(strs).map(|(s, v)| (s, Entity::AngularSize(v))), - "ANGULARITY_TOLERANCE" => AngularityTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::AngularityTolerance(v))), + "ANGULARITY_TOLERANCE" => AngularityTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::AngularityTolerance(Box::new(v)))), "ANNOTATION_CURVE_OCCURRENCE" => AnnotationCurveOccurrence_::parse_chunks(strs).map(|(s, v)| (s, Entity::AnnotationCurveOccurrence(v))), "ANNOTATION_FILL_AREA" => AnnotationFillArea_::parse_chunks(strs).map(|(s, v)| (s, Entity::AnnotationFillArea(v))), "ANNOTATION_FILL_AREA_OCCURRENCE" => AnnotationFillAreaOccurrence_::parse_chunks(strs).map(|(s, v)| (s, Entity::AnnotationFillAreaOccurrence(v))), "ANNOTATION_OCCURRENCE" => AnnotationOccurrence_::parse_chunks(strs).map(|(s, v)| (s, Entity::AnnotationOccurrence(v))), "ANNOTATION_OCCURRENCE_ASSOCIATIVITY" => AnnotationOccurrenceAssociativity_::parse_chunks(strs).map(|(s, v)| (s, Entity::AnnotationOccurrenceAssociativity(v))), "ANNOTATION_OCCURRENCE_RELATIONSHIP" => AnnotationOccurrenceRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::AnnotationOccurrenceRelationship(v))), - "ANNOTATION_PLANE" => AnnotationPlane_::parse_chunks(strs).map(|(s, v)| (s, Entity::AnnotationPlane(v))), + "ANNOTATION_PLANE" => AnnotationPlane_::parse_chunks(strs).map(|(s, v)| (s, Entity::AnnotationPlane(Box::new(v)))), "ANNOTATION_SUBFIGURE_OCCURRENCE" => AnnotationSubfigureOccurrence_::parse_chunks(strs).map(|(s, v)| (s, Entity::AnnotationSubfigureOccurrence(v))), "ANNOTATION_SYMBOL" => AnnotationSymbol_::parse_chunks(strs).map(|(s, v)| (s, Entity::AnnotationSymbol(v))), "ANNOTATION_SYMBOL_OCCURRENCE" => AnnotationSymbolOccurrence_::parse_chunks(strs).map(|(s, v)| (s, Entity::AnnotationSymbolOccurrence(v))), @@ -37130,7 +37132,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "AREA_MEASURE_WITH_UNIT" => AreaMeasureWithUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::AreaMeasureWithUnit(v))), "AREA_UNIT" => AreaUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::AreaUnit(v))), "ASIN_FUNCTION" => AsinFunction_::parse_chunks(strs).map(|(s, v)| (s, Entity::AsinFunction(v))), - "ASSEMBLY_COMPONENT_USAGE" => AssemblyComponentUsage_::parse_chunks(strs).map(|(s, v)| (s, Entity::AssemblyComponentUsage(v))), + "ASSEMBLY_COMPONENT_USAGE" => AssemblyComponentUsage_::parse_chunks(strs).map(|(s, v)| (s, Entity::AssemblyComponentUsage(Box::new(v)))), "ASSEMBLY_COMPONENT_USAGE_SUBSTITUTE" => AssemblyComponentUsageSubstitute_::parse_chunks(strs).map(|(s, v)| (s, Entity::AssemblyComponentUsageSubstitute(v))), "ATAN_FUNCTION" => AtanFunction_::parse_chunks(strs).map(|(s, v)| (s, Entity::AtanFunction(v))), "ATTRIBUTE_CLASSIFICATION_ASSIGNMENT" => AttributeClassificationAssignment_::parse_chunks(strs).map(|(s, v)| (s, Entity::AttributeClassificationAssignment(v))), @@ -37142,14 +37144,14 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "AXIS2_PLACEMENT_3D" => Axis2Placement3d_::parse_chunks(strs).map(|(s, v)| (s, Entity::Axis2Placement3d(v))), "B_SPLINE_CURVE" => BSplineCurve_::parse_chunks(strs).map(|(s, v)| (s, Entity::BSplineCurve(v))), "B_SPLINE_CURVE_WITH_KNOTS" => BSplineCurveWithKnots_::parse_chunks(strs).map(|(s, v)| (s, Entity::BSplineCurveWithKnots(Box::new(v)))), - "B_SPLINE_SURFACE" => BSplineSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::BSplineSurface(v))), + "B_SPLINE_SURFACE" => BSplineSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::BSplineSurface(Box::new(v)))), "B_SPLINE_SURFACE_WITH_KNOTS" => BSplineSurfaceWithKnots_::parse_chunks(strs).map(|(s, v)| (s, Entity::BSplineSurfaceWithKnots(Box::new(v)))), "BACKGROUND_COLOUR" => BackgroundColour_::parse_chunks(strs).map(|(s, v)| (s, Entity::BackgroundColour(v))), "BARRING_HOLE" => BarringHole_::parse_chunks(strs).map(|(s, v)| (s, Entity::BarringHole(v))), "BEAD" => Bead_::parse_chunks(strs).map(|(s, v)| (s, Entity::Bead(v))), "BEAD_END" => BeadEnd_::parse_chunks(strs).map(|(s, v)| (s, Entity::BeadEnd(v))), "BEZIER_CURVE" => BezierCurve_::parse_chunks(strs).map(|(s, v)| (s, Entity::BezierCurve(v))), - "BEZIER_SURFACE" => BezierSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::BezierSurface(v))), + "BEZIER_SURFACE" => BezierSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::BezierSurface(Box::new(v)))), "BINARY_BOOLEAN_EXPRESSION" => BinaryBooleanExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::BinaryBooleanExpression(v))), "BINARY_FUNCTION_CALL" => BinaryFunctionCall_::parse_chunks(strs).map(|(s, v)| (s, Entity::BinaryFunctionCall(v))), "BINARY_GENERIC_EXPRESSION" => BinaryGenericExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::BinaryGenericExpression(v))), @@ -37180,9 +37182,9 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "CAMERA_MODEL_D3_WITH_HLHSR" => CameraModelD3WithHlhsr_::parse_chunks(strs).map(|(s, v)| (s, Entity::CameraModelD3WithHlhsr(v))), "CAMERA_USAGE" => CameraUsage_::parse_chunks(strs).map(|(s, v)| (s, Entity::CameraUsage(v))), "CARTESIAN_POINT" => CartesianPoint_::parse_chunks(strs).map(|(s, v)| (s, Entity::CartesianPoint(v))), - "CARTESIAN_TRANSFORMATION_OPERATOR" => CartesianTransformationOperator_::parse_chunks(strs).map(|(s, v)| (s, Entity::CartesianTransformationOperator(v))), - "CARTESIAN_TRANSFORMATION_OPERATOR_2D" => CartesianTransformationOperator2d_::parse_chunks(strs).map(|(s, v)| (s, Entity::CartesianTransformationOperator2d(v))), - "CARTESIAN_TRANSFORMATION_OPERATOR_3D" => CartesianTransformationOperator3d_::parse_chunks(strs).map(|(s, v)| (s, Entity::CartesianTransformationOperator3d(v))), + "CARTESIAN_TRANSFORMATION_OPERATOR" => CartesianTransformationOperator_::parse_chunks(strs).map(|(s, v)| (s, Entity::CartesianTransformationOperator(Box::new(v)))), + "CARTESIAN_TRANSFORMATION_OPERATOR_2D" => CartesianTransformationOperator2d_::parse_chunks(strs).map(|(s, v)| (s, Entity::CartesianTransformationOperator2d(Box::new(v)))), + "CARTESIAN_TRANSFORMATION_OPERATOR_3D" => CartesianTransformationOperator3d_::parse_chunks(strs).map(|(s, v)| (s, Entity::CartesianTransformationOperator3d(Box::new(v)))), "CELSIUS_TEMPERATURE_MEASURE_WITH_UNIT" => CelsiusTemperatureMeasureWithUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::CelsiusTemperatureMeasureWithUnit(v))), "CENTRE_OF_SYMMETRY" => CentreOfSymmetry_::parse_chunks(strs).map(|(s, v)| (s, Entity::CentreOfSymmetry(v))), "CERTIFICATION" => Certification_::parse_chunks(strs).map(|(s, v)| (s, Entity::Certification(v))), @@ -37190,13 +37192,13 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "CERTIFICATION_TYPE" => CertificationType_::parse_chunks(strs).map(|(s, v)| (s, Entity::CertificationType(v))), "CHAMFER" => Chamfer_::parse_chunks(strs).map(|(s, v)| (s, Entity::Chamfer(v))), "CHAMFER_OFFSET" => ChamferOffset_::parse_chunks(strs).map(|(s, v)| (s, Entity::ChamferOffset(v))), - "CHARACTER_GLYPH_SYMBOL" => CharacterGlyphSymbol_::parse_chunks(strs).map(|(s, v)| (s, Entity::CharacterGlyphSymbol(v))), - "CHARACTERIZED_CLASS" => CharacterizedClass_::parse_chunks(strs).map(|(s, v)| (s, Entity::CharacterizedClass(v))), + "CHARACTER_GLYPH_SYMBOL" => CharacterGlyphSymbol_::parse_chunks(strs).map(|(s, v)| (s, Entity::CharacterGlyphSymbol(Box::new(v)))), + "CHARACTERIZED_CLASS" => CharacterizedClass_::parse_chunks(strs).map(|(s, v)| (s, Entity::CharacterizedClass(Box::new(v)))), "CHARACTERIZED_OBJECT" => CharacterizedObject_::parse_chunks(strs).map(|(s, v)| (s, Entity::CharacterizedObject(v))), "CIRCLE" => Circle_::parse_chunks(strs).map(|(s, v)| (s, Entity::Circle(v))), "CIRCULAR_CLOSED_PROFILE" => CircularClosedProfile_::parse_chunks(strs).map(|(s, v)| (s, Entity::CircularClosedProfile(v))), "CIRCULAR_PATTERN" => CircularPattern_::parse_chunks(strs).map(|(s, v)| (s, Entity::CircularPattern(v))), - "CIRCULAR_RUNOUT_TOLERANCE" => CircularRunoutTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::CircularRunoutTolerance(v))), + "CIRCULAR_RUNOUT_TOLERANCE" => CircularRunoutTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::CircularRunoutTolerance(Box::new(v)))), "CLASS" => Class_::parse_chunks(strs).map(|(s, v)| (s, Entity::Class(v))), "CLASS_SYSTEM" => ClassSystem_::parse_chunks(strs).map(|(s, v)| (s, Entity::ClassSystem(v))), "CLASS_USAGE_EFFECTIVITY_CONTEXT_ASSIGNMENT" => ClassUsageEffectivityContextAssignment_::parse_chunks(strs).map(|(s, v)| (s, Entity::ClassUsageEffectivityContextAssignment(v))), @@ -37204,11 +37206,11 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "CLASSIFICATION_ROLE" => ClassificationRole_::parse_chunks(strs).map(|(s, v)| (s, Entity::ClassificationRole(v))), "CLOSED_PATH_PROFILE" => ClosedPathProfile_::parse_chunks(strs).map(|(s, v)| (s, Entity::ClosedPathProfile(v))), "CLOSED_SHELL" => ClosedShell_::parse_chunks(strs).map(|(s, v)| (s, Entity::ClosedShell(v))), - "COAXIALITY_TOLERANCE" => CoaxialityTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::CoaxialityTolerance(v))), + "COAXIALITY_TOLERANCE" => CoaxialityTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::CoaxialityTolerance(Box::new(v)))), "COLOUR" => Colour_::parse_chunks(strs).map(|(s, v)| (s, Entity::Colour(v))), "COLOUR_RGB" => ColourRgb_::parse_chunks(strs).map(|(s, v)| (s, Entity::ColourRgb(v))), "COLOUR_SPECIFICATION" => ColourSpecification_::parse_chunks(strs).map(|(s, v)| (s, Entity::ColourSpecification(v))), - "COMMON_DATUM" => CommonDatum_::parse_chunks(strs).map(|(s, v)| (s, Entity::CommonDatum(v))), + "COMMON_DATUM" => CommonDatum_::parse_chunks(strs).map(|(s, v)| (s, Entity::CommonDatum(Box::new(v)))), "COMPARISON_EQUAL" => ComparisonEqual_::parse_chunks(strs).map(|(s, v)| (s, Entity::ComparisonEqual(v))), "COMPARISON_EXPRESSION" => ComparisonExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::ComparisonExpression(v))), "COMPARISON_GREATER" => ComparisonGreater_::parse_chunks(strs).map(|(s, v)| (s, Entity::ComparisonGreater(v))), @@ -37222,24 +37224,24 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "COMPOSITE_HOLE" => CompositeHole_::parse_chunks(strs).map(|(s, v)| (s, Entity::CompositeHole(v))), "COMPOSITE_SHAPE_ASPECT" => CompositeShapeAspect_::parse_chunks(strs).map(|(s, v)| (s, Entity::CompositeShapeAspect(v))), "COMPOSITE_TEXT" => CompositeText_::parse_chunks(strs).map(|(s, v)| (s, Entity::CompositeText(v))), - "COMPOSITE_TEXT_WITH_ASSOCIATED_CURVES" => CompositeTextWithAssociatedCurves_::parse_chunks(strs).map(|(s, v)| (s, Entity::CompositeTextWithAssociatedCurves(v))), + "COMPOSITE_TEXT_WITH_ASSOCIATED_CURVES" => CompositeTextWithAssociatedCurves_::parse_chunks(strs).map(|(s, v)| (s, Entity::CompositeTextWithAssociatedCurves(Box::new(v)))), "COMPOSITE_TEXT_WITH_BLANKING_BOX" => CompositeTextWithBlankingBox_::parse_chunks(strs).map(|(s, v)| (s, Entity::CompositeTextWithBlankingBox(v))), "COMPOSITE_TEXT_WITH_EXTENT" => CompositeTextWithExtent_::parse_chunks(strs).map(|(s, v)| (s, Entity::CompositeTextWithExtent(v))), "COMPOUND_FEATURE" => CompoundFeature_::parse_chunks(strs).map(|(s, v)| (s, Entity::CompoundFeature(v))), "COMPOUND_REPRESENTATION_ITEM" => CompoundRepresentationItem_::parse_chunks(strs).map(|(s, v)| (s, Entity::CompoundRepresentationItem(v))), "COMPOUND_SHAPE_REPRESENTATION" => CompoundShapeRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::CompoundShapeRepresentation(v))), "CONCAT_EXPRESSION" => ConcatExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConcatExpression(v))), - "CONCENTRICITY_TOLERANCE" => ConcentricityTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConcentricityTolerance(v))), + "CONCENTRICITY_TOLERANCE" => ConcentricityTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConcentricityTolerance(Box::new(v)))), "CONCEPT_FEATURE_OPERATOR" => ConceptFeatureOperator_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConceptFeatureOperator(v))), "CONCEPT_FEATURE_RELATIONSHIP" => ConceptFeatureRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConceptFeatureRelationship(v))), "CONCEPT_FEATURE_RELATIONSHIP_WITH_CONDITION" => ConceptFeatureRelationshipWithCondition_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConceptFeatureRelationshipWithCondition(v))), "CONDITIONAL_CONCEPT_FEATURE" => ConditionalConceptFeature_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConditionalConceptFeature(v))), - "CONFIGURABLE_ITEM" => ConfigurableItem_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConfigurableItem(v))), + "CONFIGURABLE_ITEM" => ConfigurableItem_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConfigurableItem(Box::new(v)))), "CONFIGURATION_DEFINITION" => ConfigurationDefinition_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConfigurationDefinition(v))), "CONFIGURATION_DESIGN" => ConfigurationDesign_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConfigurationDesign(v))), "CONFIGURATION_EFFECTIVITY" => ConfigurationEffectivity_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConfigurationEffectivity(v))), "CONFIGURATION_INTERPOLATION" => ConfigurationInterpolation_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConfigurationInterpolation(v))), - "CONFIGURATION_ITEM" => ConfigurationItem_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConfigurationItem(v))), + "CONFIGURATION_ITEM" => ConfigurationItem_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConfigurationItem(Box::new(v)))), "CONFIGURED_EFFECTIVITY_ASSIGNMENT" => ConfiguredEffectivityAssignment_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConfiguredEffectivityAssignment(v))), "CONFIGURED_EFFECTIVITY_CONTEXT_ASSIGNMENT" => ConfiguredEffectivityContextAssignment_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConfiguredEffectivityContextAssignment(v))), "CONIC" => Conic_::parse_chunks(strs).map(|(s, v)| (s, Entity::Conic(v))), @@ -37251,7 +37253,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "CONSTRUCTIVE_GEOMETRY_REPRESENTATION_RELATIONSHIP" => ConstructiveGeometryRepresentationRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::ConstructiveGeometryRepresentationRelationship(v))), "CONTACT_RATIO_REPRESENTATION" => ContactRatioRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::ContactRatioRepresentation(v))), "CONTEXT_DEPENDENT_INVISIBILITY" => ContextDependentInvisibility_::parse_chunks(strs).map(|(s, v)| (s, Entity::ContextDependentInvisibility(v))), - "CONTEXT_DEPENDENT_OVER_RIDING_STYLED_ITEM" => ContextDependentOverRidingStyledItem_::parse_chunks(strs).map(|(s, v)| (s, Entity::ContextDependentOverRidingStyledItem(v))), + "CONTEXT_DEPENDENT_OVER_RIDING_STYLED_ITEM" => ContextDependentOverRidingStyledItem_::parse_chunks(strs).map(|(s, v)| (s, Entity::ContextDependentOverRidingStyledItem(Box::new(v)))), "CONTEXT_DEPENDENT_SHAPE_REPRESENTATION" => ContextDependentShapeRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::ContextDependentShapeRepresentation(v))), "CONTEXT_DEPENDENT_UNIT" => ContextDependentUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::ContextDependentUnit(v))), "CONTRACT" => Contract_::parse_chunks(strs).map(|(s, v)| (s, Entity::Contract(v))), @@ -37272,7 +37274,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "CURVE_STYLE_RENDERING" => CurveStyleRendering_::parse_chunks(strs).map(|(s, v)| (s, Entity::CurveStyleRendering(v))), "CURVE_SWEPT_SOLID_SHAPE_REPRESENTATION" => CurveSweptSolidShapeRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::CurveSweptSolidShapeRepresentation(v))), "CYLINDRICAL_PAIR" => CylindricalPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::CylindricalPair(v))), - "CYLINDRICAL_PAIR_RANGE" => CylindricalPairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::CylindricalPairRange(v))), + "CYLINDRICAL_PAIR_RANGE" => CylindricalPairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::CylindricalPairRange(Box::new(v)))), "CYLINDRICAL_PAIR_VALUE" => CylindricalPairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::CylindricalPairValue(v))), "CYLINDRICAL_SURFACE" => CylindricalSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::CylindricalSurface(v))), "CYLINDRICITY_TOLERANCE" => CylindricityTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::CylindricityTolerance(v))), @@ -37284,11 +37286,11 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "DATE_ROLE" => DateRole_::parse_chunks(strs).map(|(s, v)| (s, Entity::DateRole(v))), "DATE_TIME_ROLE" => DateTimeRole_::parse_chunks(strs).map(|(s, v)| (s, Entity::DateTimeRole(v))), "DATED_EFFECTIVITY" => DatedEffectivity_::parse_chunks(strs).map(|(s, v)| (s, Entity::DatedEffectivity(v))), - "DATUM" => Datum_::parse_chunks(strs).map(|(s, v)| (s, Entity::Datum(v))), + "DATUM" => Datum_::parse_chunks(strs).map(|(s, v)| (s, Entity::Datum(Box::new(v)))), "DATUM_FEATURE" => DatumFeature_::parse_chunks(strs).map(|(s, v)| (s, Entity::DatumFeature(v))), "DATUM_FEATURE_CALLOUT" => DatumFeatureCallout_::parse_chunks(strs).map(|(s, v)| (s, Entity::DatumFeatureCallout(v))), "DATUM_REFERENCE" => DatumReference_::parse_chunks(strs).map(|(s, v)| (s, Entity::DatumReference(v))), - "DATUM_TARGET" => DatumTarget_::parse_chunks(strs).map(|(s, v)| (s, Entity::DatumTarget(v))), + "DATUM_TARGET" => DatumTarget_::parse_chunks(strs).map(|(s, v)| (s, Entity::DatumTarget(Box::new(v)))), "DATUM_TARGET_CALLOUT" => DatumTargetCallout_::parse_chunks(strs).map(|(s, v)| (s, Entity::DatumTargetCallout(v))), "DEFAULT_TOLERANCE_TABLE" => DefaultToleranceTable_::parse_chunks(strs).map(|(s, v)| (s, Entity::DefaultToleranceTable(v))), "DEFAULT_TOLERANCE_TABLE_CELL" => DefaultToleranceTableCell_::parse_chunks(strs).map(|(s, v)| (s, Entity::DefaultToleranceTableCell(v))), @@ -37310,10 +37312,10 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "DIMENSION_CALLOUT_RELATIONSHIP" => DimensionCalloutRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::DimensionCalloutRelationship(v))), "DIMENSION_CURVE" => DimensionCurve_::parse_chunks(strs).map(|(s, v)| (s, Entity::DimensionCurve(v))), "DIMENSION_CURVE_DIRECTED_CALLOUT" => DimensionCurveDirectedCallout_::parse_chunks(strs).map(|(s, v)| (s, Entity::DimensionCurveDirectedCallout(v))), - "DIMENSION_CURVE_TERMINATOR" => DimensionCurveTerminator_::parse_chunks(strs).map(|(s, v)| (s, Entity::DimensionCurveTerminator(v))), + "DIMENSION_CURVE_TERMINATOR" => DimensionCurveTerminator_::parse_chunks(strs).map(|(s, v)| (s, Entity::DimensionCurveTerminator(Box::new(v)))), "DIMENSION_PAIR" => DimensionPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::DimensionPair(v))), "DIMENSION_RELATED_TOLERANCE_ZONE_ELEMENT" => DimensionRelatedToleranceZoneElement_::parse_chunks(strs).map(|(s, v)| (s, Entity::DimensionRelatedToleranceZoneElement(v))), - "DIMENSION_TEXT_ASSOCIATIVITY" => DimensionTextAssociativity_::parse_chunks(strs).map(|(s, v)| (s, Entity::DimensionTextAssociativity(v))), + "DIMENSION_TEXT_ASSOCIATIVITY" => DimensionTextAssociativity_::parse_chunks(strs).map(|(s, v)| (s, Entity::DimensionTextAssociativity(Box::new(v)))), "DIMENSIONAL_CHARACTERISTIC_REPRESENTATION" => DimensionalCharacteristicRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::DimensionalCharacteristicRepresentation(v))), "DIMENSIONAL_EXPONENTS" => DimensionalExponents_::parse_chunks(strs).map(|(s, v)| (s, Entity::DimensionalExponents(v))), "DIMENSIONAL_LOCATION" => DimensionalLocation_::parse_chunks(strs).map(|(s, v)| (s, Entity::DimensionalLocation(v))), @@ -37327,7 +37329,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "DIRECTION_SHAPE_REPRESENTATION" => DirectionShapeRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::DirectionShapeRepresentation(v))), "DIV_EXPRESSION" => DivExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::DivExpression(v))), "DOCUMENT" => Document_::parse_chunks(strs).map(|(s, v)| (s, Entity::Document(v))), - "DOCUMENT_FILE" => DocumentFile_::parse_chunks(strs).map(|(s, v)| (s, Entity::DocumentFile(v))), + "DOCUMENT_FILE" => DocumentFile_::parse_chunks(strs).map(|(s, v)| (s, Entity::DocumentFile(Box::new(v)))), "DOCUMENT_PRODUCT_ASSOCIATION" => DocumentProductAssociation_::parse_chunks(strs).map(|(s, v)| (s, Entity::DocumentProductAssociation(v))), "DOCUMENT_PRODUCT_EQUIVALENCE" => DocumentProductEquivalence_::parse_chunks(strs).map(|(s, v)| (s, Entity::DocumentProductEquivalence(v))), "DOCUMENT_REFERENCE" => DocumentReference_::parse_chunks(strs).map(|(s, v)| (s, Entity::DocumentReference(v))), @@ -37349,13 +37351,13 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "DRAUGHTING_SPECIFICATION_REFERENCE" => DraughtingSpecificationReference_::parse_chunks(strs).map(|(s, v)| (s, Entity::DraughtingSpecificationReference(v))), "DRAUGHTING_SUBFIGURE_REPRESENTATION" => DraughtingSubfigureRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::DraughtingSubfigureRepresentation(v))), "DRAUGHTING_SYMBOL_REPRESENTATION" => DraughtingSymbolRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::DraughtingSymbolRepresentation(v))), - "DRAUGHTING_TEXT_LITERAL_WITH_DELINEATION" => DraughtingTextLiteralWithDelineation_::parse_chunks(strs).map(|(s, v)| (s, Entity::DraughtingTextLiteralWithDelineation(v))), + "DRAUGHTING_TEXT_LITERAL_WITH_DELINEATION" => DraughtingTextLiteralWithDelineation_::parse_chunks(strs).map(|(s, v)| (s, Entity::DraughtingTextLiteralWithDelineation(Box::new(v)))), "DRAUGHTING_TITLE" => DraughtingTitle_::parse_chunks(strs).map(|(s, v)| (s, Entity::DraughtingTitle(v))), "DRAWING_DEFINITION" => DrawingDefinition_::parse_chunks(strs).map(|(s, v)| (s, Entity::DrawingDefinition(v))), "DRAWING_REVISION" => DrawingRevision_::parse_chunks(strs).map(|(s, v)| (s, Entity::DrawingRevision(v))), "DRAWING_REVISION_SEQUENCE" => DrawingRevisionSequence_::parse_chunks(strs).map(|(s, v)| (s, Entity::DrawingRevisionSequence(v))), "DRAWING_SHEET_LAYOUT" => DrawingSheetLayout_::parse_chunks(strs).map(|(s, v)| (s, Entity::DrawingSheetLayout(v))), - "DRAWING_SHEET_REVISION" => DrawingSheetRevision_::parse_chunks(strs).map(|(s, v)| (s, Entity::DrawingSheetRevision(v))), + "DRAWING_SHEET_REVISION" => DrawingSheetRevision_::parse_chunks(strs).map(|(s, v)| (s, Entity::DrawingSheetRevision(Box::new(v)))), "DRAWING_SHEET_REVISION_USAGE" => DrawingSheetRevisionUsage_::parse_chunks(strs).map(|(s, v)| (s, Entity::DrawingSheetRevisionUsage(v))), "EDGE" => Edge_::parse_chunks(strs).map(|(s, v)| (s, Entity::Edge(v))), "EDGE_BASED_WIREFRAME_MODEL" => EdgeBasedWireframeModel_::parse_chunks(strs).map(|(s, v)| (s, Entity::EdgeBasedWireframeModel(v))), @@ -37394,7 +37396,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "EXTERNALLY_DEFINED_CURVE_FONT" => ExternallyDefinedCurveFont_::parse_chunks(strs).map(|(s, v)| (s, Entity::ExternallyDefinedCurveFont(v))), "EXTERNALLY_DEFINED_DIMENSION_DEFINITION" => ExternallyDefinedDimensionDefinition_::parse_chunks(strs).map(|(s, v)| (s, Entity::ExternallyDefinedDimensionDefinition(v))), "EXTERNALLY_DEFINED_FEATURE_DEFINITION" => ExternallyDefinedFeatureDefinition_::parse_chunks(strs).map(|(s, v)| (s, Entity::ExternallyDefinedFeatureDefinition(v))), - "EXTERNALLY_DEFINED_GENERAL_PROPERTY" => ExternallyDefinedGeneralProperty_::parse_chunks(strs).map(|(s, v)| (s, Entity::ExternallyDefinedGeneralProperty(v))), + "EXTERNALLY_DEFINED_GENERAL_PROPERTY" => ExternallyDefinedGeneralProperty_::parse_chunks(strs).map(|(s, v)| (s, Entity::ExternallyDefinedGeneralProperty(Box::new(v)))), "EXTERNALLY_DEFINED_HATCH_STYLE" => ExternallyDefinedHatchStyle_::parse_chunks(strs).map(|(s, v)| (s, Entity::ExternallyDefinedHatchStyle(v))), "EXTERNALLY_DEFINED_ITEM" => ExternallyDefinedItem_::parse_chunks(strs).map(|(s, v)| (s, Entity::ExternallyDefinedItem(v))), "EXTERNALLY_DEFINED_ITEM_RELATIONSHIP" => ExternallyDefinedItemRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::ExternallyDefinedItemRelationship(v))), @@ -37451,7 +37453,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "GEOMETRIC_SET" => GeometricSet_::parse_chunks(strs).map(|(s, v)| (s, Entity::GeometricSet(v))), "GEOMETRIC_TOLERANCE" => GeometricTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::GeometricTolerance(v))), "GEOMETRIC_TOLERANCE_RELATIONSHIP" => GeometricToleranceRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::GeometricToleranceRelationship(v))), - "GEOMETRIC_TOLERANCE_WITH_DATUM_REFERENCE" => GeometricToleranceWithDatumReference_::parse_chunks(strs).map(|(s, v)| (s, Entity::GeometricToleranceWithDatumReference(v))), + "GEOMETRIC_TOLERANCE_WITH_DATUM_REFERENCE" => GeometricToleranceWithDatumReference_::parse_chunks(strs).map(|(s, v)| (s, Entity::GeometricToleranceWithDatumReference(Box::new(v)))), "GEOMETRIC_TOLERANCE_WITH_DEFINED_UNIT" => GeometricToleranceWithDefinedUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::GeometricToleranceWithDefinedUnit(v))), "GEOMETRICAL_TOLERANCE_CALLOUT" => GeometricalToleranceCallout_::parse_chunks(strs).map(|(s, v)| (s, Entity::GeometricalToleranceCallout(v))), "GEOMETRICALLY_BOUNDED_2D_WIREFRAME_REPRESENTATION" => GeometricallyBounded2dWireframeRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::GeometricallyBounded2dWireframeRepresentation(v))), @@ -37464,10 +37466,10 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "GROUP_RELATIONSHIP" => GroupRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::GroupRelationship(v))), "HALF_SPACE_SOLID" => HalfSpaceSolid_::parse_chunks(strs).map(|(s, v)| (s, Entity::HalfSpaceSolid(v))), "HARDNESS_REPRESENTATION" => HardnessRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::HardnessRepresentation(v))), - "HIDDEN_ELEMENT_OVER_RIDING_STYLED_ITEM" => HiddenElementOverRidingStyledItem_::parse_chunks(strs).map(|(s, v)| (s, Entity::HiddenElementOverRidingStyledItem(v))), + "HIDDEN_ELEMENT_OVER_RIDING_STYLED_ITEM" => HiddenElementOverRidingStyledItem_::parse_chunks(strs).map(|(s, v)| (s, Entity::HiddenElementOverRidingStyledItem(Box::new(v)))), "HOLE_BOTTOM" => HoleBottom_::parse_chunks(strs).map(|(s, v)| (s, Entity::HoleBottom(v))), "HOLE_IN_PANEL" => HoleInPanel_::parse_chunks(strs).map(|(s, v)| (s, Entity::HoleInPanel(v))), - "HOMOKINETIC_PAIR" => HomokineticPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::HomokineticPair(v))), + "HOMOKINETIC_PAIR" => HomokineticPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::HomokineticPair(Box::new(v)))), "HYPERBOLA" => Hyperbola_::parse_chunks(strs).map(|(s, v)| (s, Entity::Hyperbola(v))), "ID_ATTRIBUTE" => IdAttribute_::parse_chunks(strs).map(|(s, v)| (s, Entity::IdAttribute(v))), "IDENTIFICATION_ASSIGNMENT" => IdentificationAssignment_::parse_chunks(strs).map(|(s, v)| (s, Entity::IdentificationAssignment(v))), @@ -37475,7 +37477,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "INCLUSION_PRODUCT_CONCEPT_FEATURE" => InclusionProductConceptFeature_::parse_chunks(strs).map(|(s, v)| (s, Entity::InclusionProductConceptFeature(v))), "INDEX_EXPRESSION" => IndexExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::IndexExpression(v))), "INITIAL_STATE" => InitialState_::parse_chunks(strs).map(|(s, v)| (s, Entity::InitialState(v))), - "INSTANCED_FEATURE" => InstancedFeature_::parse_chunks(strs).map(|(s, v)| (s, Entity::InstancedFeature(v))), + "INSTANCED_FEATURE" => InstancedFeature_::parse_chunks(strs).map(|(s, v)| (s, Entity::InstancedFeature(Box::new(v)))), "INT_LITERAL" => IntLiteral_::parse_chunks(strs).map(|(s, v)| (s, Entity::IntLiteral(v))), "INT_NUMERIC_VARIABLE" => IntNumericVariable_::parse_chunks(strs).map(|(s, v)| (s, Entity::IntNumericVariable(v))), "INT_VALUE_FUNCTION" => IntValueFunction_::parse_chunks(strs).map(|(s, v)| (s, Entity::IntValueFunction(v))), @@ -37519,9 +37521,9 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "LIGHT_SOURCE_AMBIENT" => LightSourceAmbient_::parse_chunks(strs).map(|(s, v)| (s, Entity::LightSourceAmbient(v))), "LIGHT_SOURCE_DIRECTIONAL" => LightSourceDirectional_::parse_chunks(strs).map(|(s, v)| (s, Entity::LightSourceDirectional(v))), "LIGHT_SOURCE_POSITIONAL" => LightSourcePositional_::parse_chunks(strs).map(|(s, v)| (s, Entity::LightSourcePositional(v))), - "LIGHT_SOURCE_SPOT" => LightSourceSpot_::parse_chunks(strs).map(|(s, v)| (s, Entity::LightSourceSpot(v))), + "LIGHT_SOURCE_SPOT" => LightSourceSpot_::parse_chunks(strs).map(|(s, v)| (s, Entity::LightSourceSpot(Box::new(v)))), "LIKE_EXPRESSION" => LikeExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::LikeExpression(v))), - "LIMITS_AND_FITS" => LimitsAndFits_::parse_chunks(strs).map(|(s, v)| (s, Entity::LimitsAndFits(v))), + "LIMITS_AND_FITS" => LimitsAndFits_::parse_chunks(strs).map(|(s, v)| (s, Entity::LimitsAndFits(Box::new(v)))), "LINE" => Line_::parse_chunks(strs).map(|(s, v)| (s, Entity::Line(v))), "LINE_PROFILE_TOLERANCE" => LineProfileTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::LineProfileTolerance(v))), "LINEAR_DIMENSION" => LinearDimension_::parse_chunks(strs).map(|(s, v)| (s, Entity::LinearDimension(v))), @@ -37536,7 +37538,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "LOT_EFFECTIVITY" => LotEffectivity_::parse_chunks(strs).map(|(s, v)| (s, Entity::LotEffectivity(v))), "LUMINOUS_INTENSITY_MEASURE_WITH_UNIT" => LuminousIntensityMeasureWithUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::LuminousIntensityMeasureWithUnit(v))), "LUMINOUS_INTENSITY_UNIT" => LuminousIntensityUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::LuminousIntensityUnit(v))), - "MAKE_FROM_USAGE_OPTION" => MakeFromUsageOption_::parse_chunks(strs).map(|(s, v)| (s, Entity::MakeFromUsageOption(v))), + "MAKE_FROM_USAGE_OPTION" => MakeFromUsageOption_::parse_chunks(strs).map(|(s, v)| (s, Entity::MakeFromUsageOption(Box::new(v)))), "MANIFOLD_SOLID_BREP" => ManifoldSolidBrep_::parse_chunks(strs).map(|(s, v)| (s, Entity::ManifoldSolidBrep(v))), "MANIFOLD_SUBSURFACE_SHAPE_REPRESENTATION" => ManifoldSubsurfaceShapeRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::ManifoldSubsurfaceShapeRepresentation(v))), "MANIFOLD_SURFACE_SHAPE_REPRESENTATION" => ManifoldSurfaceShapeRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::ManifoldSurfaceShapeRepresentation(v))), @@ -37548,7 +37550,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "MATERIAL_PROPERTY" => MaterialProperty_::parse_chunks(strs).map(|(s, v)| (s, Entity::MaterialProperty(v))), "MATERIAL_PROPERTY_REPRESENTATION" => MaterialPropertyRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::MaterialPropertyRepresentation(v))), "MAXIMUM_FUNCTION" => MaximumFunction_::parse_chunks(strs).map(|(s, v)| (s, Entity::MaximumFunction(v))), - "MEASURE_QUALIFICATION" => MeasureQualification_::parse_chunks(strs).map(|(s, v)| (s, Entity::MeasureQualification(v))), + "MEASURE_QUALIFICATION" => MeasureQualification_::parse_chunks(strs).map(|(s, v)| (s, Entity::MeasureQualification(Box::new(v)))), "MEASURE_REPRESENTATION_ITEM" => MeasureRepresentationItem_::parse_chunks(strs).map(|(s, v)| (s, Entity::MeasureRepresentationItem(v))), "MEASURE_WITH_UNIT" => MeasureWithUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::MeasureWithUnit(v))), "MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_AREA" => MechanicalDesignGeometricPresentationArea_::parse_chunks(strs).map(|(s, v)| (s, Entity::MechanicalDesignGeometricPresentationArea(v))), @@ -37564,7 +37566,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "MOMENTS_OF_INERTIA_REPRESENTATION" => MomentsOfInertiaRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::MomentsOfInertiaRepresentation(v))), "MOTION_LINK_RELATIONSHIP" => MotionLinkRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::MotionLinkRelationship(v))), "MULT_EXPRESSION" => MultExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::MultExpression(v))), - "MULTI_LANGUAGE_ATTRIBUTE_ASSIGNMENT" => MultiLanguageAttributeAssignment_::parse_chunks(strs).map(|(s, v)| (s, Entity::MultiLanguageAttributeAssignment(v))), + "MULTI_LANGUAGE_ATTRIBUTE_ASSIGNMENT" => MultiLanguageAttributeAssignment_::parse_chunks(strs).map(|(s, v)| (s, Entity::MultiLanguageAttributeAssignment(Box::new(v)))), "MULTIPLE_ARITY_BOOLEAN_EXPRESSION" => MultipleArityBooleanExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::MultipleArityBooleanExpression(v))), "MULTIPLE_ARITY_FUNCTION_CALL" => MultipleArityFunctionCall_::parse_chunks(strs).map(|(s, v)| (s, Entity::MultipleArityFunctionCall(v))), "MULTIPLE_ARITY_GENERIC_EXPRESSION" => MultipleArityGenericExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::MultipleArityGenericExpression(v))), @@ -37573,7 +37575,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "NAME_ATTRIBUTE" => NameAttribute_::parse_chunks(strs).map(|(s, v)| (s, Entity::NameAttribute(v))), "NAMED_UNIT" => NamedUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::NamedUnit(v))), "NAMED_UNIT_VARIABLE" => NamedUnitVariable_::parse_chunks(strs).map(|(s, v)| (s, Entity::NamedUnitVariable(v))), - "NEXT_ASSEMBLY_USAGE_OCCURRENCE" => NextAssemblyUsageOccurrence_::parse_chunks(strs).map(|(s, v)| (s, Entity::NextAssemblyUsageOccurrence(v))), + "NEXT_ASSEMBLY_USAGE_OCCURRENCE" => NextAssemblyUsageOccurrence_::parse_chunks(strs).map(|(s, v)| (s, Entity::NextAssemblyUsageOccurrence(Box::new(v)))), "NGON_CLOSED_PROFILE" => NgonClosedProfile_::parse_chunks(strs).map(|(s, v)| (s, Entity::NgonClosedProfile(v))), "NON_MANIFOLD_SURFACE_SHAPE_REPRESENTATION" => NonManifoldSurfaceShapeRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::NonManifoldSurfaceShapeRepresentation(v))), "NOT_EXPRESSION" => NotExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::NotExpression(v))), @@ -37612,7 +37614,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "PAIR_VALUE" => PairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::PairValue(v))), "PARABOLA" => Parabola_::parse_chunks(strs).map(|(s, v)| (s, Entity::Parabola(v))), "PARALLEL_OFFSET" => ParallelOffset_::parse_chunks(strs).map(|(s, v)| (s, Entity::ParallelOffset(v))), - "PARALLELISM_TOLERANCE" => ParallelismTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::ParallelismTolerance(v))), + "PARALLELISM_TOLERANCE" => ParallelismTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::ParallelismTolerance(Box::new(v)))), "PARAMETRIC_REPRESENTATION_CONTEXT" => ParametricRepresentationContext_::parse_chunks(strs).map(|(s, v)| (s, Entity::ParametricRepresentationContext(v))), "PARTIAL_CIRCULAR_PROFILE" => PartialCircularProfile_::parse_chunks(strs).map(|(s, v)| (s, Entity::PartialCircularProfile(v))), "PATH" => Path_::parse_chunks(strs).map(|(s, v)| (s, Entity::Path(v))), @@ -37622,23 +37624,23 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "PATTERN_OMIT_MEMBERSHIP" => PatternOmitMembership_::parse_chunks(strs).map(|(s, v)| (s, Entity::PatternOmitMembership(v))), "PCURVE" => Pcurve_::parse_chunks(strs).map(|(s, v)| (s, Entity::Pcurve(v))), "PERPENDICULAR_TO" => PerpendicularTo_::parse_chunks(strs).map(|(s, v)| (s, Entity::PerpendicularTo(v))), - "PERPENDICULARITY_TOLERANCE" => PerpendicularityTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::PerpendicularityTolerance(v))), - "PERSON" => Person_::parse_chunks(strs).map(|(s, v)| (s, Entity::Person(v))), + "PERPENDICULARITY_TOLERANCE" => PerpendicularityTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::PerpendicularityTolerance(Box::new(v)))), + "PERSON" => Person_::parse_chunks(strs).map(|(s, v)| (s, Entity::Person(Box::new(v)))), "PERSON_AND_ORGANIZATION" => PersonAndOrganization_::parse_chunks(strs).map(|(s, v)| (s, Entity::PersonAndOrganization(v))), "PERSON_AND_ORGANIZATION_ADDRESS" => PersonAndOrganizationAddress_::parse_chunks(strs).map(|(s, v)| (s, Entity::PersonAndOrganizationAddress(Box::new(v)))), "PERSON_AND_ORGANIZATION_ASSIGNMENT" => PersonAndOrganizationAssignment_::parse_chunks(strs).map(|(s, v)| (s, Entity::PersonAndOrganizationAssignment(v))), "PERSON_AND_ORGANIZATION_ROLE" => PersonAndOrganizationRole_::parse_chunks(strs).map(|(s, v)| (s, Entity::PersonAndOrganizationRole(v))), "PERSONAL_ADDRESS" => PersonalAddress_::parse_chunks(strs).map(|(s, v)| (s, Entity::PersonalAddress(Box::new(v)))), - "PHYSICALLY_MODELLED_PRODUCT_DEFINITION" => PhysicallyModelledProductDefinition_::parse_chunks(strs).map(|(s, v)| (s, Entity::PhysicallyModelledProductDefinition(v))), - "PLACED_DATUM_TARGET_FEATURE" => PlacedDatumTargetFeature_::parse_chunks(strs).map(|(s, v)| (s, Entity::PlacedDatumTargetFeature(v))), + "PHYSICALLY_MODELLED_PRODUCT_DEFINITION" => PhysicallyModelledProductDefinition_::parse_chunks(strs).map(|(s, v)| (s, Entity::PhysicallyModelledProductDefinition(Box::new(v)))), + "PLACED_DATUM_TARGET_FEATURE" => PlacedDatumTargetFeature_::parse_chunks(strs).map(|(s, v)| (s, Entity::PlacedDatumTargetFeature(Box::new(v)))), "PLACED_FEATURE" => PlacedFeature_::parse_chunks(strs).map(|(s, v)| (s, Entity::PlacedFeature(v))), "PLACEMENT" => Placement_::parse_chunks(strs).map(|(s, v)| (s, Entity::Placement(v))), "PLANAR_BOX" => PlanarBox_::parse_chunks(strs).map(|(s, v)| (s, Entity::PlanarBox(v))), - "PLANAR_CURVE_PAIR" => PlanarCurvePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::PlanarCurvePair(v))), + "PLANAR_CURVE_PAIR" => PlanarCurvePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::PlanarCurvePair(Box::new(v)))), "PLANAR_CURVE_PAIR_RANGE" => PlanarCurvePairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::PlanarCurvePairRange(v))), "PLANAR_EXTENT" => PlanarExtent_::parse_chunks(strs).map(|(s, v)| (s, Entity::PlanarExtent(v))), "PLANAR_PAIR" => PlanarPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::PlanarPair(v))), - "PLANAR_PAIR_RANGE" => PlanarPairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::PlanarPairRange(v))), + "PLANAR_PAIR_RANGE" => PlanarPairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::PlanarPairRange(Box::new(v)))), "PLANAR_PAIR_VALUE" => PlanarPairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::PlanarPairValue(v))), "PLANAR_SHAPE_REPRESENTATION" => PlanarShapeRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::PlanarShapeRepresentation(v))), "PLANE" => Plane_::parse_chunks(strs).map(|(s, v)| (s, Entity::Plane(v))), @@ -37650,16 +37652,16 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "POCKET_BOTTOM" => PocketBottom_::parse_chunks(strs).map(|(s, v)| (s, Entity::PocketBottom(v))), "POINT" => Point_::parse_chunks(strs).map(|(s, v)| (s, Entity::Point(v))), "POINT_ON_CURVE" => PointOnCurve_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointOnCurve(v))), - "POINT_ON_PLANAR_CURVE_PAIR" => PointOnPlanarCurvePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointOnPlanarCurvePair(v))), - "POINT_ON_PLANAR_CURVE_PAIR_RANGE" => PointOnPlanarCurvePairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointOnPlanarCurvePairRange(v))), + "POINT_ON_PLANAR_CURVE_PAIR" => PointOnPlanarCurvePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointOnPlanarCurvePair(Box::new(v)))), + "POINT_ON_PLANAR_CURVE_PAIR_RANGE" => PointOnPlanarCurvePairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointOnPlanarCurvePairRange(Box::new(v)))), "POINT_ON_PLANAR_CURVE_PAIR_VALUE" => PointOnPlanarCurvePairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointOnPlanarCurvePairValue(v))), "POINT_ON_SURFACE" => PointOnSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointOnSurface(v))), - "POINT_ON_SURFACE_PAIR" => PointOnSurfacePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointOnSurfacePair(v))), - "POINT_ON_SURFACE_PAIR_RANGE" => PointOnSurfacePairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointOnSurfacePairRange(v))), + "POINT_ON_SURFACE_PAIR" => PointOnSurfacePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointOnSurfacePair(Box::new(v)))), + "POINT_ON_SURFACE_PAIR_RANGE" => PointOnSurfacePairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointOnSurfacePairRange(Box::new(v)))), "POINT_ON_SURFACE_PAIR_VALUE" => PointOnSurfacePairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointOnSurfacePairValue(v))), "POINT_PLACEMENT_SHAPE_REPRESENTATION" => PointPlacementShapeRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointPlacementShapeRepresentation(v))), "POINT_REPLICA" => PointReplica_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointReplica(v))), - "POINT_STYLE" => PointStyle_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointStyle(v))), + "POINT_STYLE" => PointStyle_::parse_chunks(strs).map(|(s, v)| (s, Entity::PointStyle(Box::new(v)))), "POLY_LOOP" => PolyLoop_::parse_chunks(strs).map(|(s, v)| (s, Entity::PolyLoop(v))), "POLYLINE" => Polyline_::parse_chunks(strs).map(|(s, v)| (s, Entity::Polyline(v))), "POSITION_TOLERANCE" => PositionTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::PositionTolerance(v))), @@ -37690,14 +37692,14 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "PRISMATIC_PAIR" => PrismaticPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::PrismaticPair(v))), "PRISMATIC_PAIR_RANGE" => PrismaticPairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::PrismaticPairRange(v))), "PRISMATIC_PAIR_VALUE" => PrismaticPairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::PrismaticPairValue(v))), - "PROCESS_OPERATION" => ProcessOperation_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProcessOperation(v))), + "PROCESS_OPERATION" => ProcessOperation_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProcessOperation(Box::new(v)))), "PROCESS_PLAN" => ProcessPlan_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProcessPlan(v))), "PROCESS_PRODUCT_ASSOCIATION" => ProcessProductAssociation_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProcessProductAssociation(v))), "PROCESS_PROPERTY_ASSOCIATION" => ProcessPropertyAssociation_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProcessPropertyAssociation(v))), - "PRODUCT" => Product_::parse_chunks(strs).map(|(s, v)| (s, Entity::Product(v))), + "PRODUCT" => Product_::parse_chunks(strs).map(|(s, v)| (s, Entity::Product(Box::new(v)))), "PRODUCT_CATEGORY" => ProductCategory_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductCategory(v))), "PRODUCT_CATEGORY_RELATIONSHIP" => ProductCategoryRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductCategoryRelationship(v))), - "PRODUCT_CLASS" => ProductClass_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductClass(v))), + "PRODUCT_CLASS" => ProductClass_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductClass(Box::new(v)))), "PRODUCT_CONCEPT" => ProductConcept_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductConcept(v))), "PRODUCT_CONCEPT_CONTEXT" => ProductConceptContext_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductConceptContext(v))), "PRODUCT_CONCEPT_FEATURE" => ProductConceptFeature_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductConceptFeature(v))), @@ -37712,40 +37714,40 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "PRODUCT_DEFINITION_CONTEXT_ROLE" => ProductDefinitionContextRole_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionContextRole(v))), "PRODUCT_DEFINITION_EFFECTIVITY" => ProductDefinitionEffectivity_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionEffectivity(v))), "PRODUCT_DEFINITION_FORMATION" => ProductDefinitionFormation_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionFormation(v))), - "PRODUCT_DEFINITION_FORMATION_RELATIONSHIP" => ProductDefinitionFormationRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionFormationRelationship(v))), + "PRODUCT_DEFINITION_FORMATION_RELATIONSHIP" => ProductDefinitionFormationRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionFormationRelationship(Box::new(v)))), "PRODUCT_DEFINITION_FORMATION_WITH_SPECIFIED_SOURCE" => ProductDefinitionFormationWithSpecifiedSource_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionFormationWithSpecifiedSource(v))), "PRODUCT_DEFINITION_OCCURRENCE_RELATIONSHIP" => ProductDefinitionOccurrenceRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionOccurrenceRelationship(v))), "PRODUCT_DEFINITION_PROCESS" => ProductDefinitionProcess_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionProcess(v))), - "PRODUCT_DEFINITION_RELATIONSHIP" => ProductDefinitionRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionRelationship(v))), - "PRODUCT_DEFINITION_RESOURCE" => ProductDefinitionResource_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionResource(v))), + "PRODUCT_DEFINITION_RELATIONSHIP" => ProductDefinitionRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionRelationship(Box::new(v)))), + "PRODUCT_DEFINITION_RESOURCE" => ProductDefinitionResource_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionResource(Box::new(v)))), "PRODUCT_DEFINITION_SHAPE" => ProductDefinitionShape_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionShape(v))), "PRODUCT_DEFINITION_SUBSTITUTE" => ProductDefinitionSubstitute_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionSubstitute(v))), - "PRODUCT_DEFINITION_USAGE" => ProductDefinitionUsage_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionUsage(v))), - "PRODUCT_DEFINITION_WITH_ASSOCIATED_DOCUMENTS" => ProductDefinitionWithAssociatedDocuments_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionWithAssociatedDocuments(v))), - "PRODUCT_IDENTIFICATION" => ProductIdentification_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductIdentification(v))), + "PRODUCT_DEFINITION_USAGE" => ProductDefinitionUsage_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionUsage(Box::new(v)))), + "PRODUCT_DEFINITION_WITH_ASSOCIATED_DOCUMENTS" => ProductDefinitionWithAssociatedDocuments_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductDefinitionWithAssociatedDocuments(Box::new(v)))), + "PRODUCT_IDENTIFICATION" => ProductIdentification_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductIdentification(Box::new(v)))), "PRODUCT_PROCESS_PLAN" => ProductProcessPlan_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductProcessPlan(v))), "PRODUCT_RELATED_PRODUCT_CATEGORY" => ProductRelatedProductCategory_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductRelatedProductCategory(v))), - "PRODUCT_SPECIFICATION" => ProductSpecification_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductSpecification(v))), + "PRODUCT_SPECIFICATION" => ProductSpecification_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProductSpecification(Box::new(v)))), "PROJECTED_ZONE_DEFINITION" => ProjectedZoneDefinition_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProjectedZoneDefinition(v))), "PROJECTION_CURVE" => ProjectionCurve_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProjectionCurve(v))), "PROJECTION_DIRECTED_CALLOUT" => ProjectionDirectedCallout_::parse_chunks(strs).map(|(s, v)| (s, Entity::ProjectionDirectedCallout(v))), - "PROMISSORY_USAGE_OCCURRENCE" => PromissoryUsageOccurrence_::parse_chunks(strs).map(|(s, v)| (s, Entity::PromissoryUsageOccurrence(v))), + "PROMISSORY_USAGE_OCCURRENCE" => PromissoryUsageOccurrence_::parse_chunks(strs).map(|(s, v)| (s, Entity::PromissoryUsageOccurrence(Box::new(v)))), "PROPERTY_DEFINITION" => PropertyDefinition_::parse_chunks(strs).map(|(s, v)| (s, Entity::PropertyDefinition(v))), "PROPERTY_DEFINITION_RELATIONSHIP" => PropertyDefinitionRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::PropertyDefinitionRelationship(v))), "PROPERTY_DEFINITION_REPRESENTATION" => PropertyDefinitionRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::PropertyDefinitionRepresentation(v))), "PROPERTY_PROCESS" => PropertyProcess_::parse_chunks(strs).map(|(s, v)| (s, Entity::PropertyProcess(v))), "QUALIFIED_REPRESENTATION_ITEM" => QualifiedRepresentationItem_::parse_chunks(strs).map(|(s, v)| (s, Entity::QualifiedRepresentationItem(v))), "QUALITATIVE_UNCERTAINTY" => QualitativeUncertainty_::parse_chunks(strs).map(|(s, v)| (s, Entity::QualitativeUncertainty(v))), - "QUANTIFIED_ASSEMBLY_COMPONENT_USAGE" => QuantifiedAssemblyComponentUsage_::parse_chunks(strs).map(|(s, v)| (s, Entity::QuantifiedAssemblyComponentUsage(v))), + "QUANTIFIED_ASSEMBLY_COMPONENT_USAGE" => QuantifiedAssemblyComponentUsage_::parse_chunks(strs).map(|(s, v)| (s, Entity::QuantifiedAssemblyComponentUsage(Box::new(v)))), "QUASI_UNIFORM_CURVE" => QuasiUniformCurve_::parse_chunks(strs).map(|(s, v)| (s, Entity::QuasiUniformCurve(v))), - "QUASI_UNIFORM_SURFACE" => QuasiUniformSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::QuasiUniformSurface(v))), - "RACK_AND_PINION_PAIR" => RackAndPinionPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::RackAndPinionPair(v))), + "QUASI_UNIFORM_SURFACE" => QuasiUniformSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::QuasiUniformSurface(Box::new(v)))), + "RACK_AND_PINION_PAIR" => RackAndPinionPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::RackAndPinionPair(Box::new(v)))), "RACK_AND_PINION_PAIR_RANGE" => RackAndPinionPairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::RackAndPinionPairRange(v))), "RACK_AND_PINION_PAIR_VALUE" => RackAndPinionPairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::RackAndPinionPairValue(v))), "RADIUS_DIMENSION" => RadiusDimension_::parse_chunks(strs).map(|(s, v)| (s, Entity::RadiusDimension(v))), "RATIO_MEASURE_WITH_UNIT" => RatioMeasureWithUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::RatioMeasureWithUnit(v))), "RATIO_UNIT" => RatioUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::RatioUnit(v))), - "RATIONAL_B_SPLINE_CURVE" => RationalBSplineCurve_::parse_chunks(strs).map(|(s, v)| (s, Entity::RationalBSplineCurve(v))), + "RATIONAL_B_SPLINE_CURVE" => RationalBSplineCurve_::parse_chunks(strs).map(|(s, v)| (s, Entity::RationalBSplineCurve(Box::new(v)))), "RATIONAL_B_SPLINE_SURFACE" => RationalBSplineSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::RationalBSplineSurface(Box::new(v)))), "REAL_DEFINED_FUNCTION" => RealDefinedFunction_::parse_chunks(strs).map(|(s, v)| (s, Entity::RealDefinedFunction(v))), "REAL_LITERAL" => RealLiteral_::parse_chunks(strs).map(|(s, v)| (s, Entity::RealLiteral(v))), @@ -37753,9 +37755,9 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "RECTANGULAR_CLOSED_PROFILE" => RectangularClosedProfile_::parse_chunks(strs).map(|(s, v)| (s, Entity::RectangularClosedProfile(v))), "RECTANGULAR_COMPOSITE_SURFACE" => RectangularCompositeSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::RectangularCompositeSurface(v))), "RECTANGULAR_PATTERN" => RectangularPattern_::parse_chunks(strs).map(|(s, v)| (s, Entity::RectangularPattern(v))), - "RECTANGULAR_TRIMMED_SURFACE" => RectangularTrimmedSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::RectangularTrimmedSurface(v))), + "RECTANGULAR_TRIMMED_SURFACE" => RectangularTrimmedSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::RectangularTrimmedSurface(Box::new(v)))), "REFERENCED_MODIFIED_DATUM" => ReferencedModifiedDatum_::parse_chunks(strs).map(|(s, v)| (s, Entity::ReferencedModifiedDatum(v))), - "RELATIVE_EVENT_OCCURRENCE" => RelativeEventOccurrence_::parse_chunks(strs).map(|(s, v)| (s, Entity::RelativeEventOccurrence(v))), + "RELATIVE_EVENT_OCCURRENCE" => RelativeEventOccurrence_::parse_chunks(strs).map(|(s, v)| (s, Entity::RelativeEventOccurrence(Box::new(v)))), "REP_ITEM_GROUP" => RepItemGroup_::parse_chunks(strs).map(|(s, v)| (s, Entity::RepItemGroup(v))), "REPARAMETRISED_COMPOSITE_CURVE_SEGMENT" => ReparametrisedCompositeCurveSegment_::parse_chunks(strs).map(|(s, v)| (s, Entity::ReparametrisedCompositeCurveSegment(v))), "REPLICATE_FEATURE" => ReplicateFeature_::parse_chunks(strs).map(|(s, v)| (s, Entity::ReplicateFeature(v))), @@ -37765,11 +37767,11 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "REPRESENTATION_MAP" => RepresentationMap_::parse_chunks(strs).map(|(s, v)| (s, Entity::RepresentationMap(v))), "REPRESENTATION_RELATIONSHIP" => RepresentationRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::RepresentationRelationship(v))), "REPRESENTATION_RELATIONSHIP_WITH_TRANSFORMATION" => RepresentationRelationshipWithTransformation_::parse_chunks(strs).map(|(s, v)| (s, Entity::RepresentationRelationshipWithTransformation(v))), - "REQUIREMENT_FOR_ACTION_RESOURCE" => RequirementForActionResource_::parse_chunks(strs).map(|(s, v)| (s, Entity::RequirementForActionResource(v))), + "REQUIREMENT_FOR_ACTION_RESOURCE" => RequirementForActionResource_::parse_chunks(strs).map(|(s, v)| (s, Entity::RequirementForActionResource(Box::new(v)))), "RESOURCE_PROPERTY" => ResourceProperty_::parse_chunks(strs).map(|(s, v)| (s, Entity::ResourceProperty(v))), "RESOURCE_PROPERTY_REPRESENTATION" => ResourcePropertyRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::ResourcePropertyRepresentation(v))), "RESOURCE_REQUIREMENT_TYPE" => ResourceRequirementType_::parse_chunks(strs).map(|(s, v)| (s, Entity::ResourceRequirementType(v))), - "RESULTING_PATH" => ResultingPath_::parse_chunks(strs).map(|(s, v)| (s, Entity::ResultingPath(v))), + "RESULTING_PATH" => ResultingPath_::parse_chunks(strs).map(|(s, v)| (s, Entity::ResultingPath(Box::new(v)))), "RETENTION" => Retention_::parse_chunks(strs).map(|(s, v)| (s, Entity::Retention(v))), "REVOLUTE_PAIR" => RevolutePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::RevolutePair(v))), "REVOLUTE_PAIR_RANGE" => RevolutePairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::RevolutePairRange(v))), @@ -37781,9 +37783,9 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "RIGHT_CIRCULAR_CONE" => RightCircularCone_::parse_chunks(strs).map(|(s, v)| (s, Entity::RightCircularCone(v))), "RIGHT_CIRCULAR_CYLINDER" => RightCircularCylinder_::parse_chunks(strs).map(|(s, v)| (s, Entity::RightCircularCylinder(v))), "ROLE_ASSOCIATION" => RoleAssociation_::parse_chunks(strs).map(|(s, v)| (s, Entity::RoleAssociation(v))), - "ROLLING_CURVE_PAIR" => RollingCurvePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::RollingCurvePair(v))), + "ROLLING_CURVE_PAIR" => RollingCurvePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::RollingCurvePair(Box::new(v)))), "ROLLING_CURVE_PAIR_VALUE" => RollingCurvePairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::RollingCurvePairValue(v))), - "ROLLING_SURFACE_PAIR" => RollingSurfacePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::RollingSurfacePair(v))), + "ROLLING_SURFACE_PAIR" => RollingSurfacePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::RollingSurfacePair(Box::new(v)))), "ROLLING_SURFACE_PAIR_VALUE" => RollingSurfacePairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::RollingSurfacePairValue(v))), "ROTATION_ABOUT_DIRECTION" => RotationAboutDirection_::parse_chunks(strs).map(|(s, v)| (s, Entity::RotationAboutDirection(v))), "ROUND_HOLE" => RoundHole_::parse_chunks(strs).map(|(s, v)| (s, Entity::RoundHole(v))), @@ -37793,7 +37795,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "RUNOUT_ZONE_DEFINITION" => RunoutZoneDefinition_::parse_chunks(strs).map(|(s, v)| (s, Entity::RunoutZoneDefinition(v))), "RUNOUT_ZONE_ORIENTATION" => RunoutZoneOrientation_::parse_chunks(strs).map(|(s, v)| (s, Entity::RunoutZoneOrientation(v))), "RUNOUT_ZONE_ORIENTATION_REFERENCE_DIRECTION" => RunoutZoneOrientationReferenceDirection_::parse_chunks(strs).map(|(s, v)| (s, Entity::RunoutZoneOrientationReferenceDirection(v))), - "SCREW_PAIR" => ScrewPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::ScrewPair(v))), + "SCREW_PAIR" => ScrewPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::ScrewPair(Box::new(v)))), "SCREW_PAIR_RANGE" => ScrewPairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::ScrewPairRange(v))), "SCREW_PAIR_VALUE" => ScrewPairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::ScrewPairValue(v))), "SEAM_CURVE" => SeamCurve_::parse_chunks(strs).map(|(s, v)| (s, Entity::SeamCurve(v))), @@ -37822,9 +37824,9 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "SIMPLE_STRING_EXPRESSION" => SimpleStringExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::SimpleStringExpression(v))), "SIN_FUNCTION" => SinFunction_::parse_chunks(strs).map(|(s, v)| (s, Entity::SinFunction(v))), "SLASH_EXPRESSION" => SlashExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::SlashExpression(v))), - "SLIDING_CURVE_PAIR" => SlidingCurvePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::SlidingCurvePair(v))), + "SLIDING_CURVE_PAIR" => SlidingCurvePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::SlidingCurvePair(Box::new(v)))), "SLIDING_CURVE_PAIR_VALUE" => SlidingCurvePairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::SlidingCurvePairValue(v))), - "SLIDING_SURFACE_PAIR" => SlidingSurfacePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::SlidingSurfacePair(v))), + "SLIDING_SURFACE_PAIR" => SlidingSurfacePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::SlidingSurfacePair(Box::new(v)))), "SLIDING_SURFACE_PAIR_VALUE" => SlidingSurfacePairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::SlidingSurfacePairValue(v))), "SLOT" => Slot_::parse_chunks(strs).map(|(s, v)| (s, Entity::Slot(v))), "SLOT_END" => SlotEnd_::parse_chunks(strs).map(|(s, v)| (s, Entity::SlotEnd(v))), @@ -37832,10 +37834,10 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "SOLID_ANGLE_UNIT" => SolidAngleUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::SolidAngleUnit(v))), "SOLID_MODEL" => SolidModel_::parse_chunks(strs).map(|(s, v)| (s, Entity::SolidModel(v))), "SOLID_REPLICA" => SolidReplica_::parse_chunks(strs).map(|(s, v)| (s, Entity::SolidReplica(v))), - "SPECIFIED_HIGHER_USAGE_OCCURRENCE" => SpecifiedHigherUsageOccurrence_::parse_chunks(strs).map(|(s, v)| (s, Entity::SpecifiedHigherUsageOccurrence(v))), + "SPECIFIED_HIGHER_USAGE_OCCURRENCE" => SpecifiedHigherUsageOccurrence_::parse_chunks(strs).map(|(s, v)| (s, Entity::SpecifiedHigherUsageOccurrence(Box::new(v)))), "SPHERE" => Sphere_::parse_chunks(strs).map(|(s, v)| (s, Entity::Sphere(v))), "SPHERICAL_PAIR" => SphericalPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::SphericalPair(v))), - "SPHERICAL_PAIR_RANGE" => SphericalPairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::SphericalPairRange(v))), + "SPHERICAL_PAIR_RANGE" => SphericalPairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::SphericalPairRange(Box::new(v)))), "SPHERICAL_PAIR_VALUE" => SphericalPairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::SphericalPairValue(v))), "SPHERICAL_SURFACE" => SphericalSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::SphericalSurface(v))), "SQL_MAPPABLE_DEFINED_FUNCTION" => SqlMappableDefinedFunction_::parse_chunks(strs).map(|(s, v)| (s, Entity::SqlMappableDefinedFunction(v))), @@ -37858,13 +37860,13 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "SURFACE_CURVE_SWEPT_AREA_SOLID" => SurfaceCurveSweptAreaSolid_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfaceCurveSweptAreaSolid(v))), "SURFACE_OF_LINEAR_EXTRUSION" => SurfaceOfLinearExtrusion_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfaceOfLinearExtrusion(v))), "SURFACE_OF_REVOLUTION" => SurfaceOfRevolution_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfaceOfRevolution(v))), - "SURFACE_PAIR" => SurfacePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfacePair(v))), + "SURFACE_PAIR" => SurfacePair_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfacePair(Box::new(v)))), "SURFACE_PAIR_RANGE" => SurfacePairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfacePairRange(v))), "SURFACE_PATCH" => SurfacePatch_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfacePatch(v))), "SURFACE_PROFILE_TOLERANCE" => SurfaceProfileTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfaceProfileTolerance(v))), "SURFACE_RENDERING_PROPERTIES" => SurfaceRenderingProperties_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfaceRenderingProperties(v))), "SURFACE_REPLICA" => SurfaceReplica_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfaceReplica(v))), - "SURFACE_SIDE_STYLE" => SurfaceSideStyle_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfaceSideStyle(v))), + "SURFACE_SIDE_STYLE" => SurfaceSideStyle_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfaceSideStyle(Box::new(v)))), "SURFACE_STYLE_BOUNDARY" => SurfaceStyleBoundary_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfaceStyleBoundary(v))), "SURFACE_STYLE_CONTROL_GRID" => SurfaceStyleControlGrid_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfaceStyleControlGrid(v))), "SURFACE_STYLE_FILL_AREA" => SurfaceStyleFillArea_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfaceStyleFillArea(v))), @@ -37880,7 +37882,7 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "SURFACE_STYLE_USAGE" => SurfaceStyleUsage_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfaceStyleUsage(v))), "SURFACE_TEXTURE_REPRESENTATION" => SurfaceTextureRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::SurfaceTextureRepresentation(v))), "SWEPT_AREA_SOLID" => SweptAreaSolid_::parse_chunks(strs).map(|(s, v)| (s, Entity::SweptAreaSolid(v))), - "SWEPT_DISK_SOLID" => SweptDiskSolid_::parse_chunks(strs).map(|(s, v)| (s, Entity::SweptDiskSolid(v))), + "SWEPT_DISK_SOLID" => SweptDiskSolid_::parse_chunks(strs).map(|(s, v)| (s, Entity::SweptDiskSolid(Box::new(v)))), "SWEPT_FACE_SOLID" => SweptFaceSolid_::parse_chunks(strs).map(|(s, v)| (s, Entity::SweptFaceSolid(v))), "SWEPT_SURFACE" => SweptSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::SweptSurface(v))), "SYMBOL_COLOUR" => SymbolColour_::parse_chunks(strs).map(|(s, v)| (s, Entity::SymbolColour(v))), @@ -37889,22 +37891,22 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "SYMBOL_STYLE" => SymbolStyle_::parse_chunks(strs).map(|(s, v)| (s, Entity::SymbolStyle(v))), "SYMBOL_TARGET" => SymbolTarget_::parse_chunks(strs).map(|(s, v)| (s, Entity::SymbolTarget(v))), "SYMMETRIC_SHAPE_ASPECT" => SymmetricShapeAspect_::parse_chunks(strs).map(|(s, v)| (s, Entity::SymmetricShapeAspect(v))), - "SYMMETRY_TOLERANCE" => SymmetryTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::SymmetryTolerance(v))), + "SYMMETRY_TOLERANCE" => SymmetryTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::SymmetryTolerance(Box::new(v)))), "TACTILE_APPEARANCE_REPRESENTATION" => TactileAppearanceRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::TactileAppearanceRepresentation(v))), "TAN_FUNCTION" => TanFunction_::parse_chunks(strs).map(|(s, v)| (s, Entity::TanFunction(v))), "TANGENT" => Tangent_::parse_chunks(strs).map(|(s, v)| (s, Entity::Tangent(v))), "TAPER" => Taper_::parse_chunks(strs).map(|(s, v)| (s, Entity::Taper(v))), "TEE_PROFILE" => TeeProfile_::parse_chunks(strs).map(|(s, v)| (s, Entity::TeeProfile(v))), "TERMINATOR_SYMBOL" => TerminatorSymbol_::parse_chunks(strs).map(|(s, v)| (s, Entity::TerminatorSymbol(v))), - "TEXT_LITERAL" => TextLiteral_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextLiteral(v))), - "TEXT_LITERAL_WITH_ASSOCIATED_CURVES" => TextLiteralWithAssociatedCurves_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextLiteralWithAssociatedCurves(v))), - "TEXT_LITERAL_WITH_BLANKING_BOX" => TextLiteralWithBlankingBox_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextLiteralWithBlankingBox(v))), - "TEXT_LITERAL_WITH_DELINEATION" => TextLiteralWithDelineation_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextLiteralWithDelineation(v))), - "TEXT_LITERAL_WITH_EXTENT" => TextLiteralWithExtent_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextLiteralWithExtent(v))), + "TEXT_LITERAL" => TextLiteral_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextLiteral(Box::new(v)))), + "TEXT_LITERAL_WITH_ASSOCIATED_CURVES" => TextLiteralWithAssociatedCurves_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextLiteralWithAssociatedCurves(Box::new(v)))), + "TEXT_LITERAL_WITH_BLANKING_BOX" => TextLiteralWithBlankingBox_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextLiteralWithBlankingBox(Box::new(v)))), + "TEXT_LITERAL_WITH_DELINEATION" => TextLiteralWithDelineation_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextLiteralWithDelineation(Box::new(v)))), + "TEXT_LITERAL_WITH_EXTENT" => TextLiteralWithExtent_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextLiteralWithExtent(Box::new(v)))), "TEXT_STRING_REPRESENTATION" => TextStringRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextStringRepresentation(v))), "TEXT_STYLE" => TextStyle_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextStyle(v))), "TEXT_STYLE_FOR_DEFINED_FONT" => TextStyleForDefinedFont_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextStyleForDefinedFont(v))), - "TEXT_STYLE_WITH_BOX_CHARACTERISTICS" => TextStyleWithBoxCharacteristics_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextStyleWithBoxCharacteristics(v))), + "TEXT_STYLE_WITH_BOX_CHARACTERISTICS" => TextStyleWithBoxCharacteristics_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextStyleWithBoxCharacteristics(Box::new(v)))), "TEXT_STYLE_WITH_MIRROR" => TextStyleWithMirror_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextStyleWithMirror(v))), "TEXT_STYLE_WITH_SPACING" => TextStyleWithSpacing_::parse_chunks(strs).map(|(s, v)| (s, Entity::TextStyleWithSpacing(v))), "THERMODYNAMIC_TEMPERATURE_MEASURE_WITH_UNIT" => ThermodynamicTemperatureMeasureWithUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::ThermodynamicTemperatureMeasureWithUnit(v))), @@ -37914,34 +37916,34 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "TIME_INTERVAL_ASSIGNMENT" => TimeIntervalAssignment_::parse_chunks(strs).map(|(s, v)| (s, Entity::TimeIntervalAssignment(v))), "TIME_INTERVAL_BASED_EFFECTIVITY" => TimeIntervalBasedEffectivity_::parse_chunks(strs).map(|(s, v)| (s, Entity::TimeIntervalBasedEffectivity(v))), "TIME_INTERVAL_ROLE" => TimeIntervalRole_::parse_chunks(strs).map(|(s, v)| (s, Entity::TimeIntervalRole(v))), - "TIME_INTERVAL_WITH_BOUNDS" => TimeIntervalWithBounds_::parse_chunks(strs).map(|(s, v)| (s, Entity::TimeIntervalWithBounds(v))), + "TIME_INTERVAL_WITH_BOUNDS" => TimeIntervalWithBounds_::parse_chunks(strs).map(|(s, v)| (s, Entity::TimeIntervalWithBounds(Box::new(v)))), "TIME_MEASURE_WITH_UNIT" => TimeMeasureWithUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::TimeMeasureWithUnit(v))), "TIME_UNIT" => TimeUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::TimeUnit(v))), "TOLERANCE_VALUE" => ToleranceValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::ToleranceValue(v))), - "TOLERANCE_ZONE" => ToleranceZone_::parse_chunks(strs).map(|(s, v)| (s, Entity::ToleranceZone(v))), + "TOLERANCE_ZONE" => ToleranceZone_::parse_chunks(strs).map(|(s, v)| (s, Entity::ToleranceZone(Box::new(v)))), "TOLERANCE_ZONE_DEFINITION" => ToleranceZoneDefinition_::parse_chunks(strs).map(|(s, v)| (s, Entity::ToleranceZoneDefinition(v))), "TOLERANCE_ZONE_FORM" => ToleranceZoneForm_::parse_chunks(strs).map(|(s, v)| (s, Entity::ToleranceZoneForm(v))), "TOPOLOGICAL_REPRESENTATION_ITEM" => TopologicalRepresentationItem_::parse_chunks(strs).map(|(s, v)| (s, Entity::TopologicalRepresentationItem(v))), "TOROIDAL_SURFACE" => ToroidalSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::ToroidalSurface(v))), "TORUS" => Torus_::parse_chunks(strs).map(|(s, v)| (s, Entity::Torus(v))), - "TOTAL_RUNOUT_TOLERANCE" => TotalRunoutTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::TotalRunoutTolerance(v))), + "TOTAL_RUNOUT_TOLERANCE" => TotalRunoutTolerance_::parse_chunks(strs).map(|(s, v)| (s, Entity::TotalRunoutTolerance(Box::new(v)))), "TRANSITION_FEATURE" => TransitionFeature_::parse_chunks(strs).map(|(s, v)| (s, Entity::TransitionFeature(v))), - "TRIMMED_CURVE" => TrimmedCurve_::parse_chunks(strs).map(|(s, v)| (s, Entity::TrimmedCurve(v))), + "TRIMMED_CURVE" => TrimmedCurve_::parse_chunks(strs).map(|(s, v)| (s, Entity::TrimmedCurve(Box::new(v)))), "TWO_DIRECTION_REPEAT_FACTOR" => TwoDirectionRepeatFactor_::parse_chunks(strs).map(|(s, v)| (s, Entity::TwoDirectionRepeatFactor(v))), "TYPE_QUALIFIER" => TypeQualifier_::parse_chunks(strs).map(|(s, v)| (s, Entity::TypeQualifier(v))), "UNARY_BOOLEAN_EXPRESSION" => UnaryBooleanExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::UnaryBooleanExpression(v))), "UNARY_FUNCTION_CALL" => UnaryFunctionCall_::parse_chunks(strs).map(|(s, v)| (s, Entity::UnaryFunctionCall(v))), "UNARY_GENERIC_EXPRESSION" => UnaryGenericExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::UnaryGenericExpression(v))), "UNARY_NUMERIC_EXPRESSION" => UnaryNumericExpression_::parse_chunks(strs).map(|(s, v)| (s, Entity::UnaryNumericExpression(v))), - "UNCERTAINTY_ASSIGNED_REPRESENTATION" => UncertaintyAssignedRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::UncertaintyAssignedRepresentation(v))), - "UNCERTAINTY_MEASURE_WITH_UNIT" => UncertaintyMeasureWithUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::UncertaintyMeasureWithUnit(v))), + "UNCERTAINTY_ASSIGNED_REPRESENTATION" => UncertaintyAssignedRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::UncertaintyAssignedRepresentation(Box::new(v)))), + "UNCERTAINTY_MEASURE_WITH_UNIT" => UncertaintyMeasureWithUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::UncertaintyMeasureWithUnit(Box::new(v)))), "UNCERTAINTY_QUALIFIER" => UncertaintyQualifier_::parse_chunks(strs).map(|(s, v)| (s, Entity::UncertaintyQualifier(v))), "UNCONSTRAINED_PAIR" => UnconstrainedPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::UnconstrainedPair(v))), "UNCONSTRAINED_PAIR_VALUE" => UnconstrainedPairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::UnconstrainedPairValue(v))), "UNIFORM_CURVE" => UniformCurve_::parse_chunks(strs).map(|(s, v)| (s, Entity::UniformCurve(v))), - "UNIFORM_SURFACE" => UniformSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::UniformSurface(v))), - "UNIVERSAL_PAIR" => UniversalPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::UniversalPair(v))), - "UNIVERSAL_PAIR_RANGE" => UniversalPairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::UniversalPairRange(v))), + "UNIFORM_SURFACE" => UniformSurface_::parse_chunks(strs).map(|(s, v)| (s, Entity::UniformSurface(Box::new(v)))), + "UNIVERSAL_PAIR" => UniversalPair_::parse_chunks(strs).map(|(s, v)| (s, Entity::UniversalPair(Box::new(v)))), + "UNIVERSAL_PAIR_RANGE" => UniversalPairRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::UniversalPairRange(Box::new(v)))), "UNIVERSAL_PAIR_VALUE" => UniversalPairValue_::parse_chunks(strs).map(|(s, v)| (s, Entity::UniversalPairValue(v))), "VALUE_FUNCTION" => ValueFunction_::parse_chunks(strs).map(|(s, v)| (s, Entity::ValueFunction(v))), "VALUE_RANGE" => ValueRange_::parse_chunks(strs).map(|(s, v)| (s, Entity::ValueRange(v))), @@ -37949,14 +37951,14 @@ impl<'a> ParseFromChunks<'a> for Entity<'a> { "VARIABLE" => Variable_::parse_chunks(strs).map(|(s, v)| (s, Entity::Variable(v))), "VARIABLE_SEMANTICS" => VariableSemantics_::parse_chunks(strs).map(|(s, v)| (s, Entity::VariableSemantics(v))), "VECTOR" => Vector_::parse_chunks(strs).map(|(s, v)| (s, Entity::Vector(v))), - "VECTOR_STYLE" => VectorStyle_::parse_chunks(strs).map(|(s, v)| (s, Entity::VectorStyle(v))), + "VECTOR_STYLE" => VectorStyle_::parse_chunks(strs).map(|(s, v)| (s, Entity::VectorStyle(Box::new(v)))), "VEE_PROFILE" => VeeProfile_::parse_chunks(strs).map(|(s, v)| (s, Entity::VeeProfile(v))), - "VERSIONED_ACTION_REQUEST" => VersionedActionRequest_::parse_chunks(strs).map(|(s, v)| (s, Entity::VersionedActionRequest(v))), - "VERSIONED_ACTION_REQUEST_RELATIONSHIP" => VersionedActionRequestRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::VersionedActionRequestRelationship(v))), + "VERSIONED_ACTION_REQUEST" => VersionedActionRequest_::parse_chunks(strs).map(|(s, v)| (s, Entity::VersionedActionRequest(Box::new(v)))), + "VERSIONED_ACTION_REQUEST_RELATIONSHIP" => VersionedActionRequestRelationship_::parse_chunks(strs).map(|(s, v)| (s, Entity::VersionedActionRequestRelationship(Box::new(v)))), "VERTEX" => Vertex_::parse_chunks(strs).map(|(s, v)| (s, Entity::Vertex(v))), "VERTEX_LOOP" => VertexLoop_::parse_chunks(strs).map(|(s, v)| (s, Entity::VertexLoop(v))), "VERTEX_POINT" => VertexPoint_::parse_chunks(strs).map(|(s, v)| (s, Entity::VertexPoint(v))), - "VIEW_VOLUME" => ViewVolume_::parse_chunks(strs).map(|(s, v)| (s, Entity::ViewVolume(Box::new(v)))), + "VIEW_VOLUME" => ViewVolume_::parse_chunks(strs).map(|(s, v)| (s, Entity::ViewVolume(v))), "VISUAL_APPEARANCE_REPRESENTATION" => VisualAppearanceRepresentation_::parse_chunks(strs).map(|(s, v)| (s, Entity::VisualAppearanceRepresentation(v))), "VOLUME_MEASURE_WITH_UNIT" => VolumeMeasureWithUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::VolumeMeasureWithUnit(v))), "VOLUME_UNIT" => VolumeUnit_::parse_chunks(strs).map(|(s, v)| (s, Entity::VolumeUnit(v))), diff --git a/step/src/parse.rs b/step/src/parse.rs index f19d381..43afec1 100644 --- a/step/src/parse.rs +++ b/step/src/parse.rs @@ -269,22 +269,16 @@ pub(crate) fn parse_complex_mapping(s: &str) -> IResult { match bstr[index + next] { b'(' => { if depth == 1 { - let name_slice = &bstr[index..(index + next)]; - name = std::str::from_utf8(name_slice) - .expect("Could not convert back to name"); + name = &s[index..index + next]; + name_tag = &s[index..index + next + 1]; args_start = index + next + 1; - let name_tag_slice = &bstr[index..(index + next + 1)]; - name_tag = std::str::from_utf8(name_tag_slice) - .expect("Could not convert tag back to name"); } depth += 1; }, b')' => { depth -= 1; if depth == 1 { - let arg_slice = &bstr[args_start..(index + next)]; - let args = std::str::from_utf8(arg_slice) - .expect("Could not convert args"); + let args = &s[args_start..index + next]; match parts.iter_mut().find(|p| p.0 == name) { Some(p) => *p = (name, name_tag, args), None => parts.push((name, name_tag, args)), diff --git a/step/src/step_file.rs b/step/src/step_file.rs index 3beef01..2843579 100644 --- a/step/src/step_file.rs +++ b/step/src/step_file.rs @@ -1,5 +1,5 @@ use log::warn; -use std::{fmt, ops::Range, sync::atomic::{AtomicBool, Ordering}}; +use std::{fmt, ops::Range}; #[cfg(feature = "rayon")] use rayon::prelude::*; @@ -33,116 +33,72 @@ impl fmt::Display for StepParseError { impl std::error::Error for StepParseError {} impl<'a> StepFile<'a> { - /// Parses a STEP file from a raw array of bytes - /// `data` must be preprocessed by [`strip_flatten`] first - pub fn parse(data: &'a [u8]) -> Result { + /// Parses a STEP file preprocessed by [`strip_flatten`] + pub fn parse(data: &'a str) -> Result { Self::parse_in_chunks(data, BYTES_PER_CHUNK, RECORDS_PER_CHUNK) } /// Parses with the given work sizes, which must not change the result. - fn parse_in_chunks(data: &'a [u8], bytes_per_chunk: usize, records_per_chunk: usize) + fn parse_in_chunks(data: &'a str, bytes_per_chunk: usize, records_per_chunk: usize) -> Result { - let blocks = Self::into_blocks(data, bytes_per_chunk)?; - let is = |i: usize, text: &[u8]| &data[blocks[i].clone()] == text; - if blocks.is_empty() || !is(0, b"ISO-10303-21;") { + let blocks = Self::into_blocks(data.as_bytes(), bytes_per_chunk)?; + let is = |i: usize, text: &str| &data[blocks[i].clone()] == text; + if blocks.is_empty() || !is(0, "ISO-10303-21;") { return Err(StepParseError::new("missing ISO-10303-21 start marker")); } - let header_start = (0..blocks.len()).position(|i| is(i, b"HEADER;")) + let header_start = (0..blocks.len()).position(|i| is(i, "HEADER;")) .ok_or_else(|| StepParseError::new("missing HEADER section"))?; let data_start = (0..blocks.len()) - .position(|i| is(i, b"DATA;")) + .position(|i| is(i, "DATA;")) .ok_or_else(|| StepParseError::new("missing DATA section"))? + 1; if header_start >= data_start - 1 || !(header_start + 1..data_start - 1) - .any(|i| is(i, b"ENDSEC;")) + .any(|i| is(i, "ENDSEC;")) { return Err(StepParseError::new("HEADER section missing ENDSEC")); } let data_end = (data_start..blocks.len()) - .find(|&i| is(i, b"ENDSEC;")) + .find(|&i| is(i, "ENDSEC;")) .ok_or_else(|| StepParseError::new("DATA section missing ENDSEC"))?; - if !(data_end + 1..blocks.len()).any(|i| is(i, b"END-ISO-10303-21;")) { + if !(data_end + 1..blocks.len()).any(|i| is(i, "END-ISO-10303-21;")) { return Err(StepParseError::new("missing END-ISO-10303-21 marker")); } - let records = &blocks[data_start..data_end]; - let chunks: Vec<_> = records.chunks(records_per_chunk).collect(); - // Records are adjacent, so one UTF-8 check usually covers a chunk. - let texts = map_in_order(chunks.len(), 1, |c| { - let c = chunks[c]; - std::str::from_utf8(&data[c[0].start..c[c.len() - 1].end]).ok() - }); - let parse_nth = |r: usize| { - let (c, range) = (r / records_per_chunk, &records[r]); - let text = match texts[c] { - Some(text) => { - let base = chunks[c][0].start; - Some(&text[range.start - base..range.end - base]) - } - None => std::str::from_utf8(&data[range.clone()]).ok(), - }; - text.and_then(|s| parse_record(s).ok()).map(|(_, (_, entity))| entity) - }; - - // Size the ID table from record headers and map each ID to its last - // record, which a sequential parse would have kept. A header that - // does not parse belongs to an invalid record, reported below. - let ids: Vec> = map_in_order(chunks.len(), 1, |c| { - chunks[c].iter().map(|r| record_id(&data[r.clone()])).collect::>() - }).into_iter().flatten().collect(); - let max_id = ids.iter().flatten().copied().max().unwrap_or(0); - let mut record_of = vec![NO_RECORD; max_id + 1]; - for (r, id) in ids.iter().enumerate() { - if let Some(id) = *id { - record_of[id] = r; + // Records are parsed in parallel chunks and applied in file order, so + // a repeated ID keeps its last record and the first invalid record is + // the one reported. + let chunks: Vec<_> = blocks[data_start..data_end].chunks(records_per_chunk).collect(); + let parsed = map_in_order(chunks.len(), 1, |c| { + let mut entities = Vec::with_capacity(chunks[c].len()); + for r in chunks[c] { + entities.push(parse_record(&data[r.clone()])?); } - } - - // Parse each ID's record straight into its slot, in parallel. Records - // shadowed by a later duplicate are parsed only to detect errors. - let failed = AtomicBool::new(false); - let out: Vec = map_in_order(max_id + 1, records_per_chunk, |id| match record_of[id] { - NO_RECORD => Entity::_EmptySlot, - r => parse_nth(r).unwrap_or_else(|| { - failed.store(true, Ordering::Relaxed); - Entity::_EmptySlot - }), - }); - if failed.into_inner() || ids.iter().enumerate().any(|(r, id)| match *id { - Some(id) => record_of[id] != r && parse_nth(r).is_none(), - None => true, - }) { - let first = map_in_order(chunks.len(), 1, |c| { - let start = c * records_per_chunk; - (start..start + chunks[c].len()).find(|&r| parse_nth(r).is_none()) - }); - let r = first.into_iter().flatten().next().expect("an invalid record"); - return Err(StepParseError::new(format!( - "invalid DATA record: {}", - String::from_utf8_lossy(&data[records[r].clone()])))); - } - + Ok(entities) + }).into_iter().collect::, StepParseError>>()?; + let max_id = map_in_order(parsed.len(), 1, |c| parsed[c].iter().map(|(id, _)| *id).max()) + .into_iter().flatten().max().unwrap_or(0); + let mut out = map_in_order(max_id + 1, records_per_chunk, |_| Entity::_EmptySlot); // One bit per ID keeps reference lookups in cache. let mut defined = vec![0u64; max_id / 64 + 1]; - for id in (0..=max_id).filter(|&id| record_of[id] != NO_RECORD) { + for (id, entity) in parsed.into_iter().flatten() { + out[id] = entity; defined[id / 64] |= 1 << (id % 64); } let errors = map_in_order(chunks.len(), 1, |c| chunks[c].iter() .find_map(|r| check_references(&data[r.clone()], &defined))); - if let Some(e) = errors.into_iter().flatten().next() { - return Err(e); + match errors.into_iter().flatten().next() { + Some(e) => Err(e), + None => Ok(Self(out)), } - - Ok(Self(out)) } /// Flattens a STEP file, removing comments and whitespace - pub fn strip_flatten(data: &[u8]) -> Result, StepParseError> { + pub fn strip_flatten(data: &[u8]) -> Result { Self::flatten_in_chunks(data, BYTES_PER_CHUNK) } /// Flattens with the given work size, which must not change the result. - fn flatten_in_chunks(data: &[u8], bytes_per_chunk: usize) -> Result, StepParseError> { + fn flatten_in_chunks(data: &[u8], bytes_per_chunk: usize) -> Result { // Chunks end after a newline, so no `/*` or `*/` spans two chunks. // Each chunk is flattened as if it starts in code; a chunk that // actually starts inside a literal or comment is flattened again. @@ -166,10 +122,10 @@ impl<'a> StepFile<'a> { } state = chunk.1; } - match state { - Lexical::Comment => Err(StepParseError::new("unterminated comment")), - Lexical::Literal => Err(StepParseError::new("unterminated string literal")), - Lexical::Code if flat.len() <= 1 => Ok(flat.pop().map(|(f, _)| f).unwrap_or_default()), + let out = match state { + Lexical::Comment => return Err(StepParseError::new("unterminated comment")), + Lexical::Literal => return Err(StepParseError::new("unterminated string literal")), + Lexical::Code if flat.len() <= 1 => flat.pop().map(|(f, _)| f).unwrap_or_default(), Lexical::Code => { let mut out = vec![0; flat.iter().map(|(f, _)| f.len()).sum()]; let mut dst = Vec::with_capacity(flat.len()); @@ -183,9 +139,13 @@ impl<'a> StepFile<'a> { dst.into_par_iter().zip(&flat).for_each(|(d, (f, _))| d.copy_from_slice(f)); #[cfg(not(feature = "rayon"))] dst.into_iter().zip(&flat).for_each(|(d, (f, _))| d.copy_from_slice(f)); - Ok(out) + out } - } + }; + debug_assert!(out.is_ascii()); + // SAFETY: `flatten_chunk` writes only ASCII: input bytes below 0x80, + // or `?` in place of other bytes. + Ok(unsafe { String::from_utf8_unchecked(out) }) } /// Splits a STEP file into individual blocks, returned as byte ranges. @@ -241,9 +201,6 @@ const BYTES_PER_CHUNK: usize = if cfg!(feature = "rayon") { 1 << 20 } else { usi /// DATA records per parallel parsing or validation task. const RECORDS_PER_CHUNK: usize = if cfg!(feature = "rayon") { 4096 } else { usize::MAX }; -/// Marks an ID that no DATA record declares. -const NO_RECORD: usize = usize::MAX; - /// Returns `[f(0), f(1), ..., f(n - 1)]`. With the `rayon` feature, tasks of /// at least `min_len` items run in parallel; smaller inputs stay on the /// calling thread. @@ -368,7 +325,7 @@ fn flatten_chunk(data: &[u8], mut state: Lexical) -> (Vec, Lexical) { (out, state) } -fn parse_record(s: &str) -> crate::parse::IResult<'_, (usize, Entity<'_>)> { +fn parse_record(s: &str) -> Result<(usize, Entity<'_>), StepParseError> { parse_entity_decl(s) .and_then(|(remaining, value)| { // Complex entity parsing consumes the full declaration; @@ -391,19 +348,15 @@ fn parse_record(s: &str) -> crate::parse::IResult<'_, (usize, Entity<'_>)> { } }) }) -} - -/// Reads the ID from a record's `#ID=` header. -fn record_id(b: &[u8]) -> Option { - let b = b.strip_prefix(b"#")?; - let end = b.iter().position(|c| *c == b'=')?; - std::str::from_utf8(&b[..end]).ok()?.parse::().ok() + .map(|(_, value)| value) + .map_err(|_| StepParseError::new(format!("invalid DATA record: {}", s))) } /// Checks explicit entity references in an original record. This is kept /// separate from `Entity::upstream`, because `$` is represented internally as /// ID 0 and fallback entities do not expose their parameters there. -fn check_references(block: &[u8], defined: &[u64]) -> Option { +fn check_references(record: &str, defined: &[u64]) -> Option { + let block = record.as_bytes(); let equals = block.iter().position(|c| *c == b'=').expect("parsed DATA declaration"); let mut in_string = false; for offset in memchr::memchr2_iter(b'\'', b'#', &block[equals + 1..]) { @@ -417,12 +370,12 @@ fn check_references(block: &[u8], defined: &[u64]) -> Option { end += 1; } if end > start { - let target_text = std::str::from_utf8(&block[start..end]).unwrap(); + let target_text = &record[start..end]; let target = target_text.parse::().ok(); if !target.map_or(false, |t| defined.get(t / 64).map_or(false, |w| w >> (t % 64) & 1 == 1)) { return Some(StepParseError::new(format!( "entity {} references undefined entity #{}", - String::from_utf8_lossy(&block[..equals]), target_text + &record[..equals], target_text ))); } } @@ -461,15 +414,15 @@ mod tests { "ISO-10303-21;HEADER;ENDSEC;DATA;{}ENDSEC;END-ISO-10303-21;", records ); - StepFile::parse(data.as_bytes()).map(|_| ()) + StepFile::parse(&data).map(|_| ()) } #[test] fn flatten_respects_literals_and_comments() { let flat = StepFile::strip_flatten(b" A /* remove; ' */ 'two words; /* keep */ it''s' ").unwrap(); - assert_eq!(flat, b"A'two words; /* keep */ it''s'"); + assert_eq!(flat, "A'two words; /* keep */ it''s'"); let flat = StepFile::strip_flatten(b"A/\xff /*'*/'two\xfe words''/*keep*/'\tB").unwrap(); - assert_eq!(flat, b"A/?'two? words''/*keep*/'B"); + assert_eq!(flat, "A/?'two? words''/*keep*/'B"); } #[test] @@ -481,9 +434,9 @@ mod tests { #[test] fn malformed_and_non_step_inputs_are_errors() { - assert!(StepFile::parse(b"**PARASOLID !").unwrap_err().to_string() + assert!(StepFile::parse("**PARASOLID !").unwrap_err().to_string() .contains("unterminated record")); - assert!(StepFile::parse(b"ISO-10303-21;HEADER;ENDSEC;").unwrap_err().to_string() + assert!(StepFile::parse("ISO-10303-21;HEADER;ENDSEC;").unwrap_err().to_string() .contains("missing DATA")); assert!(StepFile::strip_flatten(b"/* never closed").unwrap_err().to_string() .contains("unterminated comment")); @@ -500,7 +453,7 @@ mod tests { #[test] fn sparse_out_of_order_records_keep_their_ids() { - let file = StepFile::parse(b"ISO-10303-21;HEADER;ENDSEC;DATA;\ + let file = StepFile::parse("ISO-10303-21;HEADER;ENDSEC;DATA;\ #19=CARTESIAN_POINT('',(3.,7.,11.));\ #2=VERTEX_POINT('',#19);ENDSEC;END-ISO-10303-21;").unwrap(); assert_eq!(file.0.len(), 20); @@ -534,10 +487,9 @@ mod tests { #3=CARTESIAN_POINT('caf\xc3\xa9',(1.,2.,3.));\n\ #9=NOT_IN_AP214('x');\nENDSEC;\nEND-ISO-10303-21;\n"; let flat = StepFile::flatten_in_chunks(text, usize::MAX).unwrap(); - let flat_text = std::str::from_utf8(&flat).unwrap(); - assert!(flat_text.starts_with("ISO-10303-21;HEADER;ENDSEC;DATA;#3=")); - assert!(flat_text.contains("#2=VERTEX_POINT('it''s; /* not a\ncomment */',#3);")); - assert!(flat_text.contains("#3=CARTESIAN_POINT('caf??',(1.,2.,3.));")); + assert!(flat.starts_with("ISO-10303-21;HEADER;ENDSEC;DATA;#3=")); + assert!(flat.contains("#2=VERTEX_POINT('it''s; /* not a\ncomment */',#3);")); + assert!(flat.contains("#3=CARTESIAN_POINT('caf??',(1.,2.,3.));")); let step = StepFile::parse_in_chunks(&flat, usize::MAX, usize::MAX).unwrap(); let point = step.entity::(Id::new(3)).unwrap(); assert_eq!(point.coordinates.iter().map(|c| c.0).collect::>(), [1., 2., 3.]); @@ -555,10 +507,10 @@ mod tests { #[test] fn chunked_parsing_reports_the_first_error_in_file_order() { - // Both invalid records are shadowed by later duplicate IDs. - let invalid = b"ISO-10303-21;HEADER;ENDSEC;DATA;#1=lowercase(1);#2=NOT_IN_AP214(#1);\ + // Later duplicate IDs replace both invalid records. + let invalid = "ISO-10303-21;HEADER;ENDSEC;DATA;#1=lowercase(1);#2=NOT_IN_AP214(#1);\ #1=NOT_IN_AP214(1);#3=lowercase(3);#3=NOT_IN_AP214(3);ENDSEC;END-ISO-10303-21;"; - let undefined = b"ISO-10303-21;HEADER;ENDSEC;DATA;#1=NOT_IN_AP214(1);\ + let undefined = "ISO-10303-21;HEADER;ENDSEC;DATA;#1=NOT_IN_AP214(1);\ #2=NOT_IN_AP214(#8);#3=NOT_IN_AP214(#9);ENDSEC;END-ISO-10303-21;"; for bytes in 1..=invalid.len() { for records in 1..=4 {