44
55use crate :: error:: { Error , Result } ;
66use crate :: string_from_blank_padded;
7- use crate :: types:: { convert_utc_time, maybe_unlimited } ;
8- use crate :: types:: { MaybeUnavailable , UtcTime , Version } ;
7+ use crate :: types:: convert_utc_time;
8+ use crate :: types:: { UtcTime , Version } ;
99use bitflags:: bitflags;
1010use cryptoki_sys:: * ;
1111use std:: convert:: TryFrom ;
@@ -36,6 +36,17 @@ bitflags! {
3636 }
3737}
3838
39+ #[ derive( Debug , Clone , Copy ) ]
40+ /// A limiting value for the token that may or may not take an explicit value
41+ pub enum Limit {
42+ /// There is an explict value for this limit
43+ Max ( u64 ) ,
44+ /// The token does not provide information about this limit
45+ Unavailable ,
46+ /// The limit is "effectively infinite" and may be treated as such
47+ Infinite ,
48+ }
49+
3950/// Information about a token
4051#[ derive( Debug , Clone ) ]
4152pub struct TokenInfo {
@@ -44,9 +55,9 @@ pub struct TokenInfo {
4455 model : String , // 16
4556 serial_number : String , // 16
4657 flags : TokenInfoFlags ,
47- max_session_count : Option < Option < u64 > > ,
58+ max_session_count : Limit ,
4859 session_count : Option < u64 > ,
49- max_rw_session_count : Option < Option < u64 > > ,
60+ max_rw_session_count : Limit ,
5061 rw_session_count : Option < u64 > ,
5162 max_pin_len : usize ,
5263 min_pin_len : usize ,
@@ -58,6 +69,53 @@ pub struct TokenInfo {
5869 firmware_version : Version ,
5970 utc_time : Option < UtcTime > ,
6071}
72+ trait MaybeUnavailable : Sized {
73+ fn maybe_unavailable ( value : CK_ULONG ) -> Option < Self > ;
74+ }
75+
76+ impl MaybeUnavailable for usize {
77+ fn maybe_unavailable ( value : CK_ULONG ) -> Option < usize > {
78+ if value == CK_UNAVAILABLE_INFORMATION {
79+ None
80+ } else {
81+ Some ( value as usize )
82+ }
83+ }
84+ }
85+
86+ impl MaybeUnavailable for u64 {
87+ fn maybe_unavailable ( value : CK_ULONG ) -> Option < u64 > {
88+ if value == CK_UNAVAILABLE_INFORMATION {
89+ None
90+ } else {
91+ // Must have cast for when ulong is 32 bits
92+ // Must have lint suppression when ulong is 64 bits
93+ #[ allow( trivial_numeric_casts) ]
94+ Some ( value as u64 )
95+ }
96+ }
97+ }
98+
99+ /// Flattens both `Infinite` and `Unavailable` to `None`,
100+ impl From < Limit > for Option < u64 > {
101+ fn from ( limit : Limit ) -> Self {
102+ match limit {
103+ Limit :: Unavailable | Limit :: Infinite => None ,
104+ Limit :: Max ( n) => Some ( n) ,
105+ }
106+ }
107+ }
108+
109+ fn maybe_unlimited ( value : CK_ULONG ) -> Limit {
110+ match value {
111+ CK_UNAVAILABLE_INFORMATION => Limit :: Unavailable ,
112+ CK_EFFECTIVELY_INFINITE => Limit :: Infinite ,
113+ // Must have cast for when ulong is 32 bits
114+ // Must have lint suppression when ulong is 64 bits
115+ #[ allow( trivial_numeric_casts) ]
116+ _ => Limit :: Max ( value as u64 ) ,
117+ }
118+ }
61119
62120impl TokenInfo {
63121 /// An application-defined label, assigned during token initialization
@@ -280,11 +338,8 @@ impl TokenInfo {
280338 }
281339
282340 /// The maximum number of sessions that can be opened with the token at one
283- /// time by a single application
284- /// If `None`, this information was unavailable.
285- /// If `Some(None)` there is no maximum, meaning the value is effectively infinite
286- /// If `Some(Some(n))` the maximum number of sessions is `n`
287- pub fn max_session_count ( & self ) -> Option < Option < u64 > > {
341+ /// time by a single application.
342+ pub fn max_session_count ( & self ) -> Limit {
288343 self . max_session_count
289344 }
290345
@@ -295,11 +350,8 @@ impl TokenInfo {
295350 }
296351
297352 /// The maximum number of read/write sessions that can be opened with the
298- /// token at one time by a single application
299- /// If `None`, this information was unavailable.
300- /// If `Some(None)` there is no maximum, meaning the value is effectively infinite
301- /// If `Some(Some(n))` the maximum number of read/write sessions is `n`
302- pub fn max_rw_session_count ( & self ) -> Option < Option < u64 > > {
353+ /// token at one time by a single application.
354+ pub fn max_rw_session_count ( & self ) -> Limit {
303355 self . max_rw_session_count
304356 }
305357
@@ -406,7 +458,7 @@ impl TryFrom<CK_TOKEN_INFO> for TokenInfo {
406458
407459#[ cfg( test) ]
408460mod test {
409- use super :: { TokenInfo , TokenInfoFlags } ;
461+ use super :: { Limit , TokenInfo , TokenInfoFlags } ;
410462 use crate :: types:: { UtcTime , Version } ;
411463
412464 #[ test]
@@ -431,9 +483,9 @@ SO_PIN_TO_BE_CHANGED | ERROR_STATE";
431483 model : String :: from ( "Token Model" ) ,
432484 serial_number : String :: from ( "Serial Number" ) ,
433485 flags : TokenInfoFlags :: empty ( ) ,
434- max_session_count : Some ( Some ( 100 ) ) , // max == 100
435- session_count : None , // unavailable
436- max_rw_session_count : Some ( None ) , // max == infinite
486+ max_session_count : Limit :: Max ( 100 ) , // max == 100
487+ session_count : None , // unavailable
488+ max_rw_session_count : Limit :: Infinite , // max == infinite
437489 rw_session_count : Some ( 1 ) ,
438490 max_pin_len : 16 ,
439491 min_pin_len : 4 ,
@@ -458,15 +510,11 @@ SO_PIN_TO_BE_CHANGED | ERROR_STATE";
458510 model: "Token Model",
459511 serial_number: "Serial Number",
460512 flags: (empty),
461- max_session_count: Some(
462- Some(
463- 100,
464- ),
513+ max_session_count: Max(
514+ 100,
465515 ),
466516 session_count: None,
467- max_rw_session_count: Some(
468- None,
469- ),
517+ max_rw_session_count: Infinite,
470518 rw_session_count: Some(
471519 1,
472520 ),
0 commit comments