1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//! XML-to-Model parsing pipeline for 3MF files.
//!
//! This module converts XML content from a 3MF archive into the in-memory [`Model`](crate::model::Model)
//! structure. It handles the Core 3MF specification and all major extensions.
//!
//! ## Two Parsing Modes
//!
//! The parser provides two modes optimized for different use cases:
//!
//! ### DOM Mode (Default)
//!
//! The [`parse_model`] function loads the entire XML document into memory and constructs the complete
//! [`Model`](crate::model::Model) structure. This is:
//!
//! - **Fast**: Single-pass parsing with efficient XML handling
//! - **Simple**: Returns a complete model ready to use
//! - **Suitable for**: Files under 100MB (typical use case)
//!
//! ```no_run
//! use lib3mf_core::parser::parse_model;
//! use std::io::Cursor;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let xml_data = b"<model xmlns='http://schemas.microsoft.com/3dmanufacturing/core/2015/02'>...</model>";
//! let model = parse_model(Cursor::new(xml_data))?;
//! println!("Loaded {} objects", model.resources.iter_objects().count());
//! # Ok(())
//! # }
//! ```
//!
//! ### SAX/Streaming Mode (For Large Files)
//!
//! The [`streaming`] module provides event-based parsing with constant memory usage via the
//! [`ModelVisitor`](visitor::ModelVisitor) trait. This is:
//!
//! - **Memory-efficient**: Constant memory regardless of file size
//! - **Suitable for**: Files over 100MB, or memory-constrained environments
//! - **More complex**: Requires implementing visitor callbacks
//!
//! See [`streaming`] module documentation for details.
//!
//! ## Parser Architecture
//!
//! The parser is organized into specialized modules:
//!
//! ### Core Parsers
//!
//! - [`model_parser`]: Orchestrates parsing of the `<model>` root element
//! - [`mesh_parser`]: Parses `<mesh>` geometry (vertices, triangles)
//! - [`material_parser`]: Parses material resources (base materials, colors, textures, composites)
//! - [`build_parser`]: Parses `<build>` section (what to print and where)
//! - [`component_parser`]: Parses `<components>` (object references and transformations)
//!
//! ### Extension Parsers
//!
//! - [`beamlattice_parser`]: Beam Lattice Extension (structural lattices)
//! - [`slice_parser`]: Slice Extension (2D layer-based geometry for DLP/SLA)
//! - [`volumetric_parser`]: Volumetric Extension (voxel data)
//! - [`boolean_parser`]: Boolean Operations Extension (CSG operations)
//! - [`displacement_parser`]: Displacement Extension (texture-driven surface modification)
//! - [`crypto_parser`]: Digital signature metadata (always available, parses XML only)
//! - `secure_content_parser`: Secure Content Extension (encryption/decryption, requires `crypto` feature)
//!
//! ### Vendor Extensions
//!
//! - [`bambu_config`]: Bambu Studio project files (plates, filament data, print times)
//!
//! ## Crypto vs Secure Content
//!
//! The parser distinguishes between two related modules:
//!
//! - **`crypto_parser`**: Always available. Parses XML structure of `<Signature>` elements but doesn't
//! verify them. This allows reading signed files without crypto dependencies.
//! - **`secure_content_parser`**: Behind `crypto` feature. Handles encryption/decryption and signature
//! verification. Requires base64, aes-gcm, rsa, sha1, sha2, x509-parser dependencies.
//!
//! ## Error Handling
//!
//! All parsing functions return [`Result<T, Lib3mfError>`](crate::error::Result):
//!
//! - **InvalidStructure**: Malformed XML, missing required attributes, spec violations
//! - **Io**: File reading errors, ZIP errors
//! - **ResourceNotFound**: References to non-existent resource IDs
//! - **FeatureNotEnabled**: Trying to use `secure_content_parser` without `crypto` feature
//!
//! The parser never panics on invalid input.
/// Bambu Studio project file parsers (plate info, filament config, print settings).
/// Beam Lattice Extension parser.
/// Boolean Operations Extension parser.
/// Build element parser (`<build>` and `<item>` elements).
/// Component and components element parser.
/// XML-DSIG crypto structure parser (always available; no crypto operations).
/// Displacement Extension parser.
/// Materials and Properties Extension parser.
/// Mesh geometry parser (`<vertices>` and `<triangles>`).
/// Root model XML parser — main entry point for DOM-mode parsing.
/// Secure Content Extension parser (requires `crypto` feature).
/// Slice Extension parser.
/// SAX/streaming parser for memory-efficient processing of large 3MF files.
/// `ModelVisitor` trait for streaming parser callbacks.
/// Volumetric Extension parser.
/// Low-level XML parser primitives used by all parser modules.
pub use ;
pub use parse_signature;
/// Primary entry point for parsing 3MF model XML.
///
/// Converts XML content into an in-memory [`Model`](crate::model::Model) structure with all resources,
/// build instructions, and extension data.
///
/// # Parameters
///
/// - `reader`: Any type implementing `Read` (e.g., `File`, `Cursor<Vec<u8>>`, `&[u8]`)
///
/// # Returns
///
/// A complete [`Model`](crate::model::Model) with all parsed data.
///
/// # Errors
///
/// - [`Lib3mfError::InvalidStructure`](crate::error::Lib3mfError::InvalidStructure): Malformed XML or spec violations
/// - [`Lib3mfError::Io`](crate::error::Lib3mfError::Io): I/O errors reading the stream
///
/// # Examples
///
/// ```no_run
/// use lib3mf_core::parser::parse_model;
/// use lib3mf_core::archive::{ZipArchiver, ArchiveReader, find_model_path};
/// use std::fs::File;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let file = File::open("model.3mf")?;
/// let mut archive = ZipArchiver::new(file)?;
/// let model_path = find_model_path(&mut archive)?;
/// let xml_data = archive.read_entry(&model_path)?;
///
/// let model = parse_model(std::io::Cursor::new(xml_data))?;
/// println!("Parsed model with {} objects", model.resources.iter_objects().count());
/// # Ok(())
/// # }
/// ```
pub use parse_model;
pub use XmlParser;