Skip to main content

ifc_material/material/
properties.rs

1//! `IfcMaterialProperties` and its direct material/property links.
2//!
3//! IFC4 and IFC4X3 declare a concrete `IfcMaterialProperties` (an
4//! `IfcExtendedProperties` subtype). IFC2X3 declares it ABSTRACT with only a
5//! `Material` attribute, so an instance in an IFC2X3 model is refused with
6//! [`crate::MaterialError::EntityNotInSchema`].
7
8use ifc_model::EntityId;
9
10use crate::view::{borrowed_entity, optional_text, required_ref, required_refs, MaterialView};
11use crate::MaterialResult;
12
13borrowed_entity!(MaterialProperties, "IFCMATERIALPROPERTIES");
14
15impl<'m> MaterialProperties<'m> {
16    /// `IfcMaterialProperties.Name`, if given.
17    pub fn name(self) -> MaterialResult<Option<&'m str>> {
18        optional_text(
19            "IFCMATERIALPROPERTIES",
20            self.id(),
21            self.entity(),
22            self.slot("Name")?,
23            "Name",
24        )
25    }
26
27    /// `IfcMaterialProperties.Description`, if given.
28    pub fn description(self) -> MaterialResult<Option<&'m str>> {
29        optional_text(
30            "IFCMATERIALPROPERTIES",
31            self.id(),
32            self.entity(),
33            self.slot("Description")?,
34            "Description",
35        )
36    }
37
38    /// `IfcMaterialProperties.Properties`, the ids of the property set's
39    /// `IfcProperty` members. Required and must be non-empty.
40    pub fn property_ids(self) -> MaterialResult<Vec<EntityId>> {
41        required_refs(
42            "IFCMATERIALPROPERTIES",
43            self.id(),
44            self.entity(),
45            self.slot("Properties")?,
46            "Properties",
47            1,
48        )
49    }
50
51    /// `IfcMaterialProperties.Material`, the id of the `IfcMaterialDefinition`
52    /// these properties describe. Required.
53    pub fn material_id(self) -> MaterialResult<EntityId> {
54        required_ref(
55            "IFCMATERIALPROPERTIES",
56            self.id(),
57            self.entity(),
58            self.slot("Material")?,
59            "Material",
60        )
61    }
62}
63
64impl<'m> MaterialView<'m> {
65    /// Iterates every `IfcMaterialProperties` instance in the model.
66    pub fn material_properties(self) -> impl Iterator<Item = MaterialProperties<'m>> + 'm {
67        let release = self.release();
68        self.model()
69            .of_type("IFCMATERIALPROPERTIES")
70            .map(move |(id, entity)| MaterialProperties::from_known(id, entity, release))
71    }
72
73    /// Iterates every `IfcMaterialProperties` whose `Material` attribute
74    /// resolves to `material`, surfacing malformed records as errors rather
75    /// than skipping them.
76    pub fn properties_for(
77        self,
78        material: EntityId,
79    ) -> impl Iterator<Item = MaterialResult<MaterialProperties<'m>>> + 'm {
80        self.material_properties()
81            .filter_map(move |properties| match properties.material_id() {
82                Ok(id) if id == material => Some(Ok(properties)),
83                Ok(_) => None,
84                Err(error) => Some(Err(error)),
85            })
86    }
87}