cobia/cobia_collection.rs
1use crate::C;
2use crate::*;
3use std::marker::PhantomData;
4use cape_smart_pointer::CapeSmartPointer;
5
6const ICOBIACOLLECTION_UUID:CapeUUID=CapeUUID::from_slice(&[0xdeu8,0xafu8,0xeau8,0x79u8,0xd3u8,0x49u8,0x4du8,0x03u8,0xbbu8,0x05u8,0x37u8,0x7cu8,0x0du8,0x3eu8,0x47u8,0x8bu8]);
7
8/// CobiaCollectionBase wraps an collection interface
9///
10/// The collection interface is returned in case muliple objects
11/// are returned by a method.
12///
13/// Collection items each must have a unique name, and the name
14/// is exposed from the approproate identification interface.
15///
16/// Collection items are accessed by index or by name.
17///
18/// #Example
19///
20/// ```
21/// use cobia;
22/// use cobia::prelude::*;
23/// cobia::cape_open_initialize().unwrap();
24/// let library_enumerator = cobia::CapeTypeLibraries::new().unwrap();
25/// let libraries = library_enumerator.libraries().unwrap(); //this is a CobiaCollection smart pointer
26/// assert!(libraries.size() > 0); //normally the CAPE-OPEN type libraries are registered
27/// cobia::cape_open_cleanup();
28/// ```
29
30#[cape_smart_pointer(ICOBIACOLLECTION_UUID)]
31pub struct CobiaCollectionBase<Element:CapeSmartPointer> {
32 interface: *mut C::ICobiaCollection, //the interface is cast to ICapeCollection - function signatures are identical
33 element_type : PhantomData<Element>
34}
35
36impl<Element:CapeSmartPointer> CobiaCollectionBase<Element> {
37
38 /// Create a new CobiaCollectionBase from an interface pointer
39 ///
40 /// This member is not typically called. Instead, the CobiaCollectionBase is created by the API functions that return it.
41 ///
42 /// # Safety
43 ///
44 /// The interface pointer must be valid and must point to an object that implements the ICobiaCollection interface.
45 ///
46 /// # Panics
47 ///
48 /// This function panics if the interface pointer is null.
49
50 pub(crate) fn from_interface_pointer(interface: *mut C::ICobiaCollection) -> Self {
51 if interface.is_null() {
52 panic!("Null pointer in creation of CobiaCollectionBase<Element>");
53 }
54 unsafe {((*(*interface).vTbl).base.addReference.unwrap())((*interface).me)};
55 Self {
56 interface,
57 element_type: PhantomData,
58 }
59 }
60
61 /// Create a new CobiaCollectionBase from an interface pointer without adding a reference
62 ///
63 /// This member is not typically called. Instead, the CobiaCollectionBase is created by the API functions that return it.
64 ///
65 /// # Safety
66 ///
67 /// The interface pointer must be valid and must point to an object that implements the ICobiaCollection interface.
68 ///
69 /// # Panics
70 ///
71 /// This function panics if the interface pointer is null.
72
73 pub(crate) fn attach(interface: *mut C::ICobiaCollection) -> Self {
74 if interface.is_null() {
75 panic!("Null pointer in creation of CobiaCollectionBase<Element>");
76 }
77 Self {
78 interface,
79 element_type: PhantomData,
80 }
81 }
82
83 /// Get the number of elements in the collection
84 ///
85 /// # Examples
86 ///
87 /// ```
88 /// use cobia;
89 /// use cobia::prelude::*;
90 /// cobia::cape_open_initialize().unwrap();
91 /// let library_enumerator = cobia::CapeTypeLibraries::new().unwrap();
92 /// let libraries = library_enumerator.libraries().unwrap(); //this is a CobiaCollection smart pointer
93 /// assert!(libraries.size() > 0); //normally the CAPE-OPEN type libraries are registered
94 /// cobia::cape_open_cleanup();
95 /// ```
96
97 pub fn size(&self) -> usize {
98 let mut size: C::CapeInteger = 0;
99 let res=unsafe { (*(*self.interface).vTbl).getCount.unwrap()((*self.interface).me, &mut size as *mut C::CapeInteger) };
100 if res == COBIAERR_NOERROR {
101 size as usize
102 } else {
103 //getCount should not fail... if it does, assume that 0 is a reasonable default
104 debug_assert!(false);
105 0
106 }
107 }
108
109 /// Get a collection item by index in the collection
110 ///
111 /// The index is zero-based, and must be 0 <= index < size().
112 ///
113 /// Note that the collection implements iterators, but not the Index
114 /// or IndexMut trait, as both these traits require returning the
115 /// item by reference, which is not possible in this context, as
116 /// the returned object owns the interface pointer.
117 ///
118 /// # Examples
119 ///
120 /// ```
121 /// use cobia;
122 /// use cobia::prelude::*;
123 /// cobia::cape_open_initialize().unwrap();
124 /// let library_enumerator = cobia::CapeTypeLibraries::new().unwrap();
125 /// let libraries = library_enumerator.libraries().unwrap(); //this is a CobiaCollection smart pointer
126 /// assert!(libraries.size() > 0); //normally the CAPE-OPEN type libraries are registered
127 /// let library = libraries.at(0).unwrap();
128 /// cobia::cape_open_cleanup();
129 /// ```
130
131 pub fn at(&self,index : usize) -> Result<Element, COBIAError> {
132 let mut el : *mut C::ICapeInterface=std::ptr::null_mut();
133 let index = index as C::CapeInteger;
134 let res=unsafe { (*(*self.interface).vTbl).ItemByIndex.unwrap()((*self.interface).me,index,&mut el as *mut *mut C::ICapeInterface) };
135 if res == COBIAERR_NOERROR {
136 let el=el as *mut C::ICapeInterface as *mut Element::Interface;
137 if el.is_null() {
138 Err(COBIAError::Code(COBIAERR_NULLPOINTER))
139 } else {
140 Ok(Element::attach(unsafe{&mut*el as &mut Element::Interface}))
141 }
142 } else {
143 Err(COBIAError::from_object(res,self))
144 }
145 }
146
147 /// Get a collection item by name
148 ///
149 /// The name is case insentive, but must correspond to one of the items
150 /// in the collection.
151 ///
152 /// # Examples
153 ///
154 /// ```
155 /// use cobia;
156 /// use cobia::prelude::*;
157 /// cobia::cape_open_initialize().unwrap();
158 /// let library_enumerator = cobia::CapeTypeLibraries::new().unwrap();
159 /// let libraries = library_enumerator.libraries().unwrap(); //this is a CobiaCollection smart pointer
160 /// assert!(libraries.size() > 0); //normally the CAPE-OPEN type libraries are registered
161 /// let library = libraries.at(0).unwrap();
162 /// let lib_name = library.get_name().unwrap();
163 /// let library1 = libraries.get(&lib_name).unwrap();
164 /// assert_eq!(library.get_uuid().unwrap(),library1.get_uuid().unwrap());
165 /// cobia::cape_open_cleanup();
166 /// ```
167
168 pub fn get(&self,id : &str) -> Result<Element, COBIAError> {
169 let mut el : *mut C::ICapeInterface=std::ptr::null_mut();
170 let id=CapeStringImpl::from_string(id);
171 let res=unsafe { (*(*self.interface).vTbl).ItemByName.unwrap()((*self.interface).me,(&id.as_cape_string_in() as *const C::ICapeString).cast_mut(),&mut el as *mut *mut C::ICapeInterface) };
172 if res == COBIAERR_NOERROR {
173 let el=el as *mut C::ICapeInterface as *mut Element::Interface;
174 if el.is_null() {
175 Err(COBIAError::Code(COBIAERR_NULLPOINTER))
176 } else {
177 Ok(Element::attach(unsafe{&mut*el as &mut Element::Interface}))
178 }
179 } else {
180 Err(COBIAError::from_object(res,self))
181 }
182 }
183
184 ///Get an iterator for the collection by reference
185 ///
186 ///This iterator does not consume the collection.
187 ///
188 /// # Examples
189 ///
190 /// ```
191 /// use cobia;
192 /// use cobia::prelude::*;
193 /// cobia::cape_open_initialize().unwrap();
194 /// let library_enumerator = cobia::CapeTypeLibraries::new().unwrap();
195 /// let libraries = library_enumerator.libraries().unwrap(); //this is a CobiaCollection smart pointer
196 /// let mut found=false;
197 /// for library in libraries.iter() {
198 /// let lib_name = library.get_name().unwrap();
199 /// if lib_name=="CAPEOPEN_1_2" { //performance note: this is not efficient, but it is an example
200 /// found=true;
201 /// break;
202 /// }
203 /// }
204 /// assert!(found);
205 /// cobia::cape_open_cleanup();
206 /// ```
207
208 pub fn iter(&self) -> CobiaCollectionBaseRefIterator<'_,Element> {
209 CobiaCollectionBaseRefIterator {
210 collection:self,
211 index:0
212 }
213 }
214
215}
216
217/// Iterator that consumes a CobiaCollectionBase
218///
219/// This iterator consumes the collection and returns the elements.
220///
221/// # Examples
222///
223/// ```
224/// use cobia;
225/// use cobia::prelude::*;
226/// cobia::cape_open_initialize().unwrap();
227/// let library_enumerator = cobia::CapeTypeLibraries::new().unwrap();
228/// let libraries = library_enumerator.libraries().unwrap(); //this is a CobiaCollection smart pointer
229/// let mut found=false;
230/// for library in libraries {
231/// let lib_name = library.get_name().unwrap();
232/// if lib_name=="CAPEOPEN_1_2" { //performance note: this is not efficient, but it is an example
233/// found=true;
234/// break;
235/// }
236/// }
237/// assert!(found);
238/// cobia::cape_open_cleanup();
239/// ```
240
241pub struct CobiaCollectionBaseIterator<Element:CapeSmartPointer> {
242 collection:CobiaCollectionBase<Element>,
243 index:usize
244}
245
246impl<Element:CapeSmartPointer> Iterator for CobiaCollectionBaseIterator<Element> {
247 type Item=Element;
248 fn next(&mut self) -> Option<Self::Item> {
249 if self.index < self.collection.size() {
250 let res=self.collection.at(self.index);
251 self.index+=1;
252 match res {
253 Ok(el) => Some(el),
254 Err(_) => None
255 }
256 } else {
257 None
258 }
259 }
260}
261
262impl<Element:CapeSmartPointer> IntoIterator for CobiaCollectionBase<Element> {
263 type Item=Element;
264 type IntoIter=CobiaCollectionBaseIterator<Element>;
265 fn into_iter(self) -> Self::IntoIter {
266 CobiaCollectionBaseIterator {
267 collection:self,
268 index:0
269 }
270 }
271}
272
273/// Iterator that using a reference to CobiaCollectionBase
274///
275/// This iterator returns the elements and does not consume the collection.
276///
277/// # Examples
278///
279/// ```
280/// use cobia;
281/// use cobia::prelude::*;
282/// cobia::cape_open_initialize().unwrap();
283/// let library_enumerator = cobia::CapeTypeLibraries::new().unwrap();
284/// let libraries = library_enumerator.libraries().unwrap(); //this is a CobiaCollection smart pointer
285/// let mut found=false;
286/// for library in &libraries {
287/// let lib_name = library.get_name().unwrap();
288/// if lib_name=="CAPEOPEN_1_2" { //performance note: this is not efficient, but it is an example
289/// found=true;
290/// break;
291/// }
292/// }
293/// assert!(found);
294/// cobia::cape_open_cleanup();
295/// ```
296
297pub struct CobiaCollectionBaseRefIterator<'a,Element:CapeSmartPointer> {
298 collection:&'a CobiaCollectionBase<Element>,
299 index:usize
300}
301
302impl<'a,Element:CapeSmartPointer> Iterator for CobiaCollectionBaseRefIterator<'a,Element> {
303 type Item=Element;
304 fn next(&mut self) -> Option<Self::Item> {
305 if self.index < self.collection.size() {
306 let res=self.collection.at(self.index);
307 self.index+=1;
308 match res {
309 Ok(el) => Some(el),
310 Err(_) => None
311 }
312 } else {
313 None
314 }
315 }
316}
317
318impl<'a,Element:CapeSmartPointer> IntoIterator for &'a CobiaCollectionBase<Element> {
319 type Item=Element;
320 type IntoIter=CobiaCollectionBaseRefIterator<'a,Element>;
321 fn into_iter(self) -> Self::IntoIter {
322 CobiaCollectionBaseRefIterator {
323 collection:&self,
324 index:0
325 }
326 }
327}
328
329/// CobiaCollection wraps an ICobiaCollection interface
330///
331/// This interface is returned by API functions that return multiple objects.
332///
333/// #Example
334///
335/// ```
336/// use cobia;
337/// use cobia::prelude::*;
338/// cobia::cape_open_initialize().unwrap();
339/// let library_enumerator = cobia::CapeTypeLibraries::new().unwrap();
340/// let libraries = library_enumerator.libraries().unwrap(); //this is a CobiaCollection smart pointer
341/// assert!(libraries.size() > 0); //normally the CAPE-OPEN type libraries are registered
342/// cobia::cape_open_cleanup();
343/// ```
344
345pub type CobiaCollection<Element> = CobiaCollectionBase<Element>;
346