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}