distillation_shortcut_unit/port_collection.rs
1use crate::shared_unit_data::*;
2use crate::material_port::MaterialPort;
3use crate::distillation_shortcut_unit::DistillationShortcutUnit;
4use cobia::*;
5
6/// The PortCollection class implements a CAPE-OPEN 1.2 collection of unit ports for the DistillationShortcutUnit.
7///
8/// It provides methods to manage and access the ports associated with the unit.
9
10#[cape_object_implementation(
11 interfaces={
12 cape_open_1_2::ICapeIdentification,
13 cape_open_1_2::ICapeCollection<cape_open_1_2::CapeUnitPort>,
14 },
15 new_arguments={
16 shared_unit_data
17 }
18 )]
19pub(crate) struct PortCollection {
20 /// The name of the port collection
21 name: CapeStringImpl,
22 /// The description of the port collection
23 description: CapeStringImpl,
24 /// The ports contained in this collection
25 ports : Vec<cape_open_1_2::CapeUnitPort>,
26 /// Shared data for the unit, allowing access to common properties.
27 shared_unit_data: SharedUnitDataRef,
28}
29
30impl PortCollection {
31
32 /// Creates a new `PortCollection` for the distillation shortcut unit.
33 ///
34 /// # Arguments
35 /// * `shared_unit_data` - A reference to shared data for the unit, which contains common properties.
36 ///
37 /// # Returns
38 /// A new instance of `PortCollection` initialized with the provided shared data.
39
40 fn new(shared_unit_data: SharedUnitDataRef) -> Self {
41 Self {
42 name : CapeStringImpl::from(format!("{} port collection",DistillationShortcutUnit::NAME)),
43 description : CapeStringImpl::from(format!("Port collection of {}",DistillationShortcutUnit::NAME)),
44 ports: Vec::new(),
45 shared_unit_data,
46 cobia_object_data : std::default::Default::default(), //this member is generated by cape_object_implementation and can be set to default()
47 }
48 }
49
50 /// Adds a port to the collection.
51 ///
52 /// # Arguments
53 /// * `port` - The port to be added to the collection.
54
55 pub(crate) fn add_port(&mut self,port:cape_open_1_2::CapeUnitPort) {
56 self.ports.push(port);
57 }
58
59 /// Obtain an iterator to iterate over the ports in the collection.
60 ///
61 /// # Returns
62 /// An iterator that yields references to the ports in the collection.
63
64 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut cape_open_1_2::CapeUnitPort> {
65 self.ports.iter_mut()
66 }
67
68}
69
70impl std::fmt::Display for PortCollection {
71
72 /// Formats the port collection for display.
73 ///
74 /// The std::fmt::Display interface is used when generating the
75 /// source name of the object that raises an error.
76 ///
77 /// # Arguments
78 /// * `f` - A mutable reference to the formatter where the output will be written.
79 ///
80 /// # Returns
81 /// A result indicating whether the formatting was successful or not.
82
83 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84 write!(f,"Port collection of {} unit '{}'",DistillationShortcutUnit::NAME, self.shared_unit_data.borrow().name)
85 }
86
87}
88
89impl cape_open_1_2::ICapeIdentification for PortCollection {
90
91 /// Get the name of the component.
92 ///
93 /// # Arguments
94 /// * `name` - A mutable reference to a `CapeStringOut` where the name will be set.
95 ///
96 /// # Returns
97 /// * A `Result` indicating success or failure. If successful, the name is set in `name`.
98
99 fn get_component_name(&mut self,name:&mut CapeStringOut) -> Result<(), COBIAError> {
100 name.set(&self.name)?;
101 Ok(())
102 }
103
104 /// Get the description of the component.
105 ///
106 /// # Arguments
107 /// * `description` - A mutable reference to a `CapeStringOut` where the description will be set.
108 ///
109 /// # Returns
110 /// * A `Result` indicating success or failure. If successful, the description is set in `description`.
111
112 fn get_component_description(&mut self,description:&mut CapeStringOut) -> Result<(), COBIAError> {
113 description.set(&self.description)?;
114 Ok(())
115 }
116
117 /// Set the name of the component.
118 ///
119 /// # Arguments
120 /// * `name` - A reference to a `CapeStringIn` containing the new name to be set.
121 ///
122 /// # Returns
123 /// * A `Result` indicating success or failure. This method is not allowed for this port implementation and will return an error.
124
125 fn set_component_name(&mut self, _name: &CapeStringIn) -> Result<(), COBIAError> {
126 Err(cobia::COBIAError::Code(cobia::COBIAERR_DENIED))
127 }
128
129 /// Set the description of the component.
130 ///
131 /// # Arguments
132 /// * `desc` - A reference to a `CapeStringIn` containing the new description to be set.
133 ///
134 /// # Returns
135 /// * A `Result` indicating success or failure. This method is not allowed for this port implementation and will return an error.
136
137 fn set_component_description(&mut self, _desc: &CapeStringIn) -> Result<(), COBIAError> {
138 Err(cobia::COBIAError::Code(cobia::COBIAERR_DENIED))
139 }
140}
141
142impl cape_open_1_2::ICapeCollection<cape_open_1_2::CapeUnitPort> for PortCollection {
143
144 /// Retrieves a port by its index.
145 ///
146 /// # Arguments
147 /// * `index` - The index of the port to retrieve.
148 ///
149 /// # Returns
150 /// * A `Result` containing the port if found, or an error if the index is out of bounds.
151
152 fn item_by_index(&mut self,index:CapeInteger) -> Result<cape_open_1_2::CapeUnitPort,COBIAError> {
153 if index<0 || index>=self.ports.len() as CapeInteger {
154 Err(cobia::COBIAError::Code(cobia::COBIAERR_NOSUCHITEM))
155 } else {
156 Ok(self.ports[index as usize].clone())
157 }
158 }
159
160 /// Retrieves a port by its name.
161 ///
162 /// # Arguments
163 /// * `name` - A reference to a `CapeStringIn` containing the name of the port to retrieve.
164 ///
165 /// # Returns
166 /// * A `Result` containing the port if found, or an error if no such item exists.
167
168 fn item_by_name(&mut self,name:&CapeStringIn) -> Result<cape_open_1_2::CapeUnitPort,COBIAError> {
169 //in a generic implementation we could obtain the item names from the ports via ICapeIdentification,
170 // but this involves copying the string. In this particular implementation, there is only one port
171 // class to we cast the object to its class and use the name directly
172 //alternatively, for a more performant implementation if the collection is expected to contain more
173 // than a few items, we could obtain the names while adding the ports to the collection, and build
174 // a hashmap of names to ports or port indices; see 'ParameterCollection' for an example of this.
175 for port in self.ports.iter() {
176 //unsafe because we must guarantee that the implementing object is MaterialPort:
177 // (it is, as this is the only object in the collection)
178 let material_port=unsafe { MaterialPort::borrow(port) };
179 if material_port.get_name().eq_ignore_case(name) {
180 return Ok(port.clone());
181 }
182 }
183 Err(cobia::COBIAError::Code(cobia::COBIAERR_NOSUCHITEM))
184 }
185
186 /// Retrieves the number of ports in the collection.
187 ///
188 /// # Returns
189 /// * A `Result` containing the number of ports as a `CapeInteger`.
190
191 fn get_count(&mut self) -> Result<CapeInteger,COBIAError> {
192 Ok(self.ports.len() as CapeInteger)
193 }
194}