lib3mf_core/model/
resolver.rs1use crate::archive::ArchiveReader;
2use crate::error::Result;
3use crate::model::{Model, Object, ResourceId};
4use crate::parser::model_parser::parse_model;
5use std::collections::HashMap;
6use std::io::Cursor;
7
8const ROOT_PATH: &str = "ROOT";
9const MAIN_MODEL_PART: &str = "3D/3dmodel.model";
10
11pub struct PartResolver<'a, A: ArchiveReader> {
13 archive: &'a mut A,
14 models: HashMap<String, Model>,
15}
16
17impl<'a, A: ArchiveReader> PartResolver<'a, A> {
18 pub fn new(archive: &'a mut A, root_model: Model) -> Self {
19 let mut models = HashMap::new();
20 models.insert(ROOT_PATH.to_string(), root_model);
21 Self { archive, models }
22 }
23
24 pub fn resolve_object(
25 &mut self,
26 id: ResourceId,
27 path: Option<&str>,
28 ) -> Result<Option<(&Model, &Object)>> {
29 let model = self.get_or_load_model(path)?;
30 Ok(model.resources.get_object(id).map(|obj| (model, obj)))
31 }
32
33 pub fn resolve_base_materials(
34 &mut self,
35 id: ResourceId,
36 path: Option<&str>,
37 ) -> Result<Option<&crate::model::BaseMaterialsGroup>> {
38 let model = self.get_or_load_model(path)?;
39 Ok(model.resources.get_base_materials(id))
40 }
41
42 pub fn resolve_color_group(
43 &mut self,
44 id: ResourceId,
45 path: Option<&str>,
46 ) -> Result<Option<&crate::model::ColorGroup>> {
47 let model = self.get_or_load_model(path)?;
48 Ok(model.resources.get_color_group(id))
49 }
50
51 fn get_or_load_model(&mut self, path: Option<&str>) -> Result<&Model> {
52 let part_path = match path {
53 Some(p) => {
54 let p = p.trim_start_matches('/');
55 if p.is_empty() || p.eq_ignore_ascii_case(MAIN_MODEL_PART) {
56 ROOT_PATH
57 } else {
58 p
59 }
60 }
61 None => ROOT_PATH,
62 };
63
64 if !self.models.contains_key(part_path) {
65 let data = self.archive.read_entry(part_path).or_else(|_| {
66 let alt = format!("/{}", part_path);
67 self.archive.read_entry(&alt)
68 })?;
69
70 let model = parse_model(Cursor::new(data))?;
71 self.models.insert(part_path.to_string(), model);
72 }
73
74 Ok(self.models.get(part_path).unwrap())
75 }
76
77 pub fn get_root_model(&self) -> &Model {
78 self.models.get("ROOT").unwrap()
79 }
80
81 pub fn archive_mut(&mut self) -> &mut A {
82 self.archive
83 }
84}