Skip to main content

ifc_material/profile/
definition.rs

1//! `IfcMaterialProfile` semantics and authored offsets.
2
3use ifc_model::EntityId;
4
5use crate::view::{
6    borrowed_entity, optional_integer, optional_ref, optional_text, required_number_array_2,
7    required_ref, MaterialView,
8};
9use crate::{MaterialError, MaterialResult};
10
11borrowed_entity!(MaterialProfile, "IFCMATERIALPROFILE");
12borrowed_entity!(MaterialProfileWithOffsets, "IFCMATERIALPROFILEWITHOFFSETS");
13
14macro_rules! profile_accessors {
15    ($type:ident, $ifc_name:literal) => {
16        impl<'m> $type<'m> {
17            /// `Name`, if given.
18            pub fn name(self) -> MaterialResult<Option<&'m str>> {
19                optional_text(
20                    $ifc_name,
21                    self.id(),
22                    self.entity(),
23                    self.slot("Name")?,
24                    "Name",
25                )
26            }
27
28            /// `Description`, if given.
29            pub fn description(self) -> MaterialResult<Option<&'m str>> {
30                optional_text(
31                    $ifc_name,
32                    self.id(),
33                    self.entity(),
34                    self.slot("Description")?,
35                    "Description",
36                )
37            }
38
39            /// `Material`, the associated `IfcMaterial`, if given.
40            pub fn material_id(self) -> MaterialResult<Option<EntityId>> {
41                optional_ref(
42                    $ifc_name,
43                    self.id(),
44                    self.entity(),
45                    self.slot("Material")?,
46                    "Material",
47                )
48            }
49
50            /// `Profile`, the associated `IfcProfileDef`. Required.
51            pub fn profile_id(self) -> MaterialResult<EntityId> {
52                required_ref(
53                    $ifc_name,
54                    self.id(),
55                    self.entity(),
56                    self.slot("Profile")?,
57                    "Profile",
58                )
59            }
60
61            /// `Priority`, if given. Must be in `0..=100`.
62            pub fn priority(self) -> MaterialResult<Option<i64>> {
63                let value = optional_integer(
64                    $ifc_name,
65                    self.id(),
66                    self.entity(),
67                    self.slot("Priority")?,
68                    "Priority",
69                )?;
70                if value.is_some_and(|value| !(0..=100).contains(&value)) {
71                    return Err(MaterialError::InvalidValue {
72                        entity: $ifc_name,
73                        id: self.id(),
74                        attribute: "Priority",
75                        value: "expected an integer in 0..=100".to_owned(),
76                    });
77                }
78                Ok(value)
79            }
80
81            /// `Category`, if given.
82            pub fn category(self) -> MaterialResult<Option<&'m str>> {
83                optional_text(
84                    $ifc_name,
85                    self.id(),
86                    self.entity(),
87                    self.slot("Category")?,
88                    "Category",
89                )
90            }
91        }
92    };
93}
94profile_accessors!(MaterialProfile, "IFCMATERIALPROFILE");
95profile_accessors!(MaterialProfileWithOffsets, "IFCMATERIALPROFILEWITHOFFSETS");
96
97impl MaterialProfileWithOffsets<'_> {
98    /// `IfcMaterialProfileWithOffsets.OffsetValues`. Required, a 2-element
99    /// list.
100    pub fn offset_values(self) -> MaterialResult<[f64; 2]> {
101        required_number_array_2(
102            "IFCMATERIALPROFILEWITHOFFSETS",
103            self.id(),
104            self.entity(),
105            self.slot("OffsetValues")?,
106            "OffsetValues",
107        )
108    }
109}
110
111impl<'m> MaterialView<'m> {
112    /// Iterates every `IfcMaterialProfile` instance in the model.
113    pub fn profiles(self) -> impl Iterator<Item = MaterialProfile<'m>> + 'm {
114        let release = self.release();
115        self.model()
116            .of_type("IFCMATERIALPROFILE")
117            .map(move |(id, entity)| MaterialProfile::from_known(id, entity, release))
118    }
119
120    /// Iterates every `IfcMaterialProfileWithOffsets` instance in the model.
121    pub fn profiles_with_offsets(
122        self,
123    ) -> impl Iterator<Item = MaterialProfileWithOffsets<'m>> + 'm {
124        let release = self.release();
125        self.model()
126            .of_type("IFCMATERIALPROFILEWITHOFFSETS")
127            .map(move |(id, entity)| MaterialProfileWithOffsets::from_known(id, entity, release))
128    }
129}