@@ -18,6 +18,11 @@ const MAX_OBJECT_COUNT: usize = 10;
1818/// Used to iterate over the object handles returned by underlying calls to `C_FindObjects`.
1919/// The iterator is created by calling the `iter_objects` and `iter_objects_with_cache_size` methods on a `Session` object.
2020///
21+ /// # Note
22+ ///
23+ /// The iterator `new()` method will call `C_FindObjectsInit`. It means that until the iterator is dropped,
24+ /// creating another iterator will result in an error (typically `RvError::OperationActive` ).
25+ ///
2126/// # Example
2227///
2328/// ```no_run
@@ -30,47 +35,44 @@ const MAX_OBJECT_COUNT: usize = 10;
3035/// use cryptoki::types::AuthPin;
3136/// use std::env;
3237///
33- /// fn test () -> Result<(), Error> {
34- /// let pkcs11 = Pkcs11::new(
35- /// env::var("PKCS11_SOFTHSM2_MODULE")
36- /// .unwrap_or_else(|_| "/usr/local/lib/libsofthsm2.so".to_string()),
37- /// )?;
38+ /// # fn main () -> testresult::TestResult {
39+ /// let pkcs11 = Pkcs11::new(
40+ /// env::var("PKCS11_SOFTHSM2_MODULE")
41+ /// .unwrap_or_else(|_| "/usr/local/lib/libsofthsm2.so".to_string()),
42+ /// )?;
3843///
39- /// pkcs11.initialize(CInitializeArgs::OsThreads)?;
40- /// let slot = pkcs11.get_slots_with_token()?.remove(0);
44+ /// pkcs11.initialize(CInitializeArgs::OsThreads)?;
45+ /// let slot = pkcs11.get_slots_with_token()?.remove(0);
4146///
42- /// let session = pkcs11.open_ro_session(slot).unwrap();
43- /// session.login(UserType::User, Some(&AuthPin::new("fedcba".into())))?;
47+ /// let session = pkcs11.open_ro_session(slot).unwrap();
48+ /// session.login(UserType::User, Some(&AuthPin::new("fedcba".into())))?;
4449///
45- /// let token_object = vec![Attribute::Token(true)];
46- /// let wanted_attr = vec![AttributeType::Label];
50+ /// let token_object = vec![Attribute::Token(true)];
51+ /// let wanted_attr = vec![AttributeType::Label];
4752///
48- /// for (idx, obj) in session.iter_objects(&token_object)?.enumerate() {
49- /// let obj = obj?; // handle potential error condition
53+ /// for (idx, obj) in session.iter_objects(&token_object)?.enumerate() {
54+ /// let obj = obj?; // handle potential error condition
5055///
51- /// let attributes = session.get_attributes(obj, &wanted_attr)?;
56+ /// let attributes = session.get_attributes(obj, &wanted_attr)?;
5257///
53- /// match attributes.get(0) {
54- /// Some(Attribute::Label(l)) => {
55- /// println!(
56- /// "token object #{}: handle {}, label {}",
57- /// idx,
58- /// obj,
59- /// String::from_utf8(l.to_vec())
60- /// .unwrap_or_else(|_| "*** not valid utf8 ***".to_string())
61- /// );
62- /// }
63- /// _ => {
64- /// println!("token object #{}: handle {}, label not found", idx, obj);
65- /// }
58+ /// match attributes.get(0) {
59+ /// Some(Attribute::Label(l)) => {
60+ /// println!(
61+ /// "token object #{}: handle {}, label {}",
62+ /// idx,
63+ /// obj,
64+ /// String::from_utf8(l.to_vec())
65+ /// .unwrap_or_else(|_| "*** not valid utf8 ***".to_string())
66+ /// );
67+ /// }
68+ /// _ => {
69+ /// println!("token object #{}: handle {}, label not found", idx, obj);
6670/// }
6771/// }
68- /// Ok(())
6972/// }
73+ /// # Ok(())
74+ /// # }
7075///
71- /// pub fn main() {
72- /// test().unwrap();
73- /// }
7476/// ```
7577#[ derive( Debug ) ]
7678pub struct ObjectHandleIterator < ' a > {
@@ -154,8 +156,7 @@ impl<'a> Iterator for ObjectHandleIterator<'a> {
154156 )
155157 } ,
156158 None => {
157- // C_FindObjects() is not implemented on this implementation
158- // sort of unexpected. TODO: Consider panic!() instead?
159+ // C_FindObjects() is not implemented,, bark and return an error
159160 log:: error!( "C_FindObjects() is not implemented on this library" ) ;
160161 return Some ( Err ( Error :: NullFunctionPointer ) as Result < ObjectHandle > ) ;
161162 }
@@ -173,9 +174,9 @@ impl<'a> Iterator for ObjectHandleIterator<'a> {
173174
174175impl Drop for ObjectHandleIterator < ' _ > {
175176 fn drop ( & mut self ) {
176- // silently pass if C_FindObjectsFinal() is not implemented on this implementation
177- // this is unexpected. TODO: Consider panic!() instead?
177+ // bark but pass if C_FindObjectsFinal() is not implemented
178178 if let Some ( f) = get_pkcs11_func ! ( self . session. client( ) , C_FindObjectsFinal ) {
179+ log:: error!( "C_FindObjectsFinal() is not implemented on this library" ) ;
179180 // swallow the return value, as we can't do anything about it
180181 let _ = unsafe { f ( self . session . handle ( ) ) } ;
181182 }
@@ -220,17 +221,31 @@ impl Session {
220221 template : & [ Attribute ] ,
221222 cache_size : usize ,
222223 ) -> Result < ObjectHandleIterator > {
223- let template: Vec < CK_ATTRIBUTE > = template. iter ( ) . map ( |attr| attr . into ( ) ) . collect ( ) ;
224+ let template: Vec < CK_ATTRIBUTE > = template. iter ( ) . map ( Into :: into) . collect ( ) ;
224225 ObjectHandleIterator :: new ( self , template, cache_size)
225226 }
226227
227228 /// Search for session objects matching a template
228229 ///
229230 /// # Arguments
231+ ///
230232 /// * `template` - A [Attribute] of search parameters that will be used
231233 /// to find objects.
232234 ///
233- /// # Examples
235+ /// # Returns
236+ ///
237+ /// Upon success, a vector of [ObjectHandle] wrapped in a Result.
238+ /// Upon failure, the first error encountered.
239+ ///
240+ /// # Note
241+ ///
242+ /// It is a convenience method that will call [`Session::iter_objects`] and collect the results.
243+ ///
244+ /// # See also
245+ ///
246+ /// * [`Session::iter_objects`] for a way to specify the cache size
247+
248+ /// # Example
234249 ///
235250 /// ```rust
236251 /// # fn main() -> testresult::TestResult {
@@ -260,54 +275,11 @@ impl Session {
260275 /// }
261276 /// # Ok(()) }
262277 /// ```
278+ ///
279+ #[ inline( always) ]
263280 pub fn find_objects ( & self , template : & [ Attribute ] ) -> Result < Vec < ObjectHandle > > {
264- let mut template: Vec < CK_ATTRIBUTE > = template. iter ( ) . map ( |attr| attr. into ( ) ) . collect ( ) ;
265-
266- unsafe {
267- Rv :: from ( get_pkcs11 ! ( self . client( ) , C_FindObjectsInit ) (
268- self . handle ( ) ,
269- template. as_mut_ptr ( ) ,
270- template. len ( ) . try_into ( ) ?,
271- ) )
272- . into_result ( Function :: FindObjectsInit ) ?;
273- }
274-
275- let mut object_handles = [ 0 ; MAX_OBJECT_COUNT ] ;
276- let mut object_count = MAX_OBJECT_COUNT as CK_ULONG ; // set to MAX_OBJECT_COUNT to enter loop
277- let mut objects = Vec :: new ( ) ;
278-
279- // as long as the number of objects returned equals the maximum number
280- // of objects that can be returned, we keep calling C_FindObjects
281- while object_count == MAX_OBJECT_COUNT as CK_ULONG {
282- unsafe {
283- Rv :: from ( get_pkcs11 ! ( self . client( ) , C_FindObjects ) (
284- self . handle ( ) ,
285- object_handles. as_mut_ptr ( ) as CK_OBJECT_HANDLE_PTR ,
286- MAX_OBJECT_COUNT . try_into ( ) ?,
287- & mut object_count,
288- ) )
289- . into_result ( Function :: FindObjects ) ?;
290- }
291-
292- // exit loop, no more objects to be returned, no need to extend the objects vector
293- if object_count == 0 {
294- break ;
295- }
296-
297- // extend the objects vector with the new objects
298- objects. extend_from_slice ( & object_handles[ ..object_count. try_into ( ) ?] ) ;
299- }
300-
301- unsafe {
302- Rv :: from ( get_pkcs11 ! ( self . client( ) , C_FindObjectsFinal ) (
303- self . handle ( ) ,
304- ) )
305- . into_result ( Function :: FindObjectsFinal ) ?;
306- }
307-
308- let objects = objects. into_iter ( ) . map ( ObjectHandle :: new) . collect ( ) ;
309-
310- Ok ( objects)
281+ self . iter_objects ( template) ?
282+ . collect :: < Result < Vec < ObjectHandle > > > ( )
311283 }
312284
313285 /// Create a new object
0 commit comments