@@ -18,6 +18,11 @@ const MAX_OBJECT_COUNT: usize = 10;
18
18
/// Used to iterate over the object handles returned by underlying calls to `C_FindObjects`.
19
19
/// The iterator is created by calling the `iter_objects` and `iter_objects_with_cache_size` methods on a `Session` object.
20
20
///
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
+ ///
21
26
/// # Example
22
27
///
23
28
/// ```no_run
@@ -30,47 +35,44 @@ const MAX_OBJECT_COUNT: usize = 10;
30
35
/// use cryptoki::types::AuthPin;
31
36
/// use std::env;
32
37
///
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
+ /// )?;
38
43
///
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);
41
46
///
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())))?;
44
49
///
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];
47
52
///
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
50
55
///
51
- /// let attributes = session.get_attributes(obj, &wanted_attr)?;
56
+ /// let attributes = session.get_attributes(obj, &wanted_attr)?;
52
57
///
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);
66
70
/// }
67
71
/// }
68
- /// Ok(())
69
72
/// }
73
+ /// # Ok(())
74
+ /// # }
70
75
///
71
- /// pub fn main() {
72
- /// test().unwrap();
73
- /// }
74
76
/// ```
75
77
#[ derive( Debug ) ]
76
78
pub struct ObjectHandleIterator < ' a > {
@@ -154,8 +156,7 @@ impl<'a> Iterator for ObjectHandleIterator<'a> {
154
156
)
155
157
} ,
156
158
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
159
160
log:: error!( "C_FindObjects() is not implemented on this library" ) ;
160
161
return Some ( Err ( Error :: NullFunctionPointer ) as Result < ObjectHandle > ) ;
161
162
}
@@ -173,9 +174,9 @@ impl<'a> Iterator for ObjectHandleIterator<'a> {
173
174
174
175
impl Drop for ObjectHandleIterator < ' _ > {
175
176
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
178
178
if let Some ( f) = get_pkcs11_func ! ( self . session. client( ) , C_FindObjectsFinal ) {
179
+ log:: error!( "C_FindObjectsFinal() is not implemented on this library" ) ;
179
180
// swallow the return value, as we can't do anything about it
180
181
let _ = unsafe { f ( self . session . handle ( ) ) } ;
181
182
}
@@ -220,17 +221,31 @@ impl Session {
220
221
template : & [ Attribute ] ,
221
222
cache_size : usize ,
222
223
) -> 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 ( ) ;
224
225
ObjectHandleIterator :: new ( self , template, cache_size)
225
226
}
226
227
227
228
/// Search for session objects matching a template
228
229
///
229
230
/// # Arguments
231
+ ///
230
232
/// * `template` - A [Attribute] of search parameters that will be used
231
233
/// to find objects.
232
234
///
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
234
249
///
235
250
/// ```rust
236
251
/// # fn main() -> testresult::TestResult {
@@ -260,54 +275,11 @@ impl Session {
260
275
/// }
261
276
/// # Ok(()) }
262
277
/// ```
278
+ ///
279
+ #[ inline( always) ]
263
280
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 > > > ( )
311
283
}
312
284
313
285
/// Create a new object
0 commit comments