2
2
3
3
use crate :: {
4
4
Any , Choice , Decodable , Encodable , Encoder , Error , ErrorKind , Header , Length , Result , Tag ,
5
+ TagNumber ,
5
6
} ;
6
7
use core:: convert:: TryFrom ;
7
8
8
9
/// Context-specific field.
9
10
///
10
11
/// This type encodes a field which is specific to a particular context,
11
- /// and has a special "context-specific tag" (presently 0-15 supported) .
12
+ /// and is identified by a [`TagNumber`] .
12
13
///
13
14
/// Any context-specific field can be decoded/encoded with this type.
14
15
/// The intended use is to dynamically dispatch off of the context-specific
15
- /// tag when decoding, which allows support for extensions, which are denoted
16
- /// in an ASN.1 schema using the `...` ellipsis extension marker.
17
- ///
18
- ///
16
+ /// tag number when decoding, which allows support for extensions, which are
17
+ /// denoted in an ASN.1 schema using the `...` ellipsis extension marker.
19
18
#[ derive( Copy , Clone , Debug , Eq , PartialEq , PartialOrd , Ord ) ]
20
19
pub struct ContextSpecific < ' a > {
21
- /// Context-specific tag value sans the leading `0b10000000` class
20
+ /// Context-specific tag number sans the leading `0b10000000` class
22
21
/// identifier bit and `0b100000` constructed flag.
23
- pub ( crate ) tag : u8 ,
22
+ pub tag_number : TagNumber ,
24
23
25
24
/// Value of the field.
26
- pub ( crate ) value : Any < ' a > ,
27
- }
28
-
29
- impl < ' a > ContextSpecific < ' a > {
30
- /// Create a new context-specific field.
31
- ///
32
- /// The tag value includes only lower 6-bits of the context specific tag,
33
- /// sans the leading `10` high bits identifying the context-specific tag
34
- /// class as well as the constructed flag.
35
- pub fn new ( tag : u8 , value : Any < ' a > ) -> Result < Self > {
36
- // Ensure we consider the context-specific tag valid
37
- Tag :: context_specific ( tag) ?;
38
-
39
- Ok ( Self { tag, value } )
40
- }
41
-
42
- /// Get the context-specific tag for this field.
43
- ///
44
- /// The tag value includes only lower 6-bits of the context specific tag,
45
- /// sans the leading `10` high bits identifying the context-specific tag
46
- /// class as well as the constructed flag.
47
- pub fn tag ( self ) -> u8 {
48
- self . tag
49
- }
50
-
51
- /// Get the value of this context-specific tag.
52
- pub fn value ( self ) -> Any < ' a > {
53
- self . value
54
- }
25
+ pub value : Any < ' a > ,
55
26
}
56
27
57
28
impl < ' a > Choice < ' a > for ContextSpecific < ' a > {
58
29
fn can_decode ( tag : Tag ) -> bool {
59
- tag. is_context_specific ( )
30
+ matches ! ( tag, Tag :: ContextSpecific ( _ ) )
60
31
}
61
32
}
62
33
@@ -66,7 +37,7 @@ impl<'a> Encodable for ContextSpecific<'a> {
66
37
}
67
38
68
39
fn encode ( & self , encoder : & mut Encoder < ' _ > ) -> Result < ( ) > {
69
- let tag = Tag :: context_specific ( self . tag ) ? ;
40
+ let tag = Tag :: ContextSpecific ( self . tag_number ) ;
70
41
Header :: new ( tag, self . value . encoded_len ( ) ?) ?. encode ( encoder) ?;
71
42
self . value . encode ( encoder)
72
43
}
@@ -82,21 +53,17 @@ impl<'a> TryFrom<Any<'a>> for ContextSpecific<'a> {
82
53
type Error = Error ;
83
54
84
55
fn try_from ( any : Any < ' a > ) -> Result < ContextSpecific < ' a > > {
85
- let tag = if any. tag ( ) . is_context_specific ( ) {
86
- ( any . tag ( ) as u8 )
87
- . checked_sub ( 0xA0 )
88
- . ok_or ( ErrorKind :: Overflow ) ?
89
- } else {
90
- return Err ( ErrorKind :: UnexpectedTag {
56
+ match any. tag ( ) {
57
+ Tag :: ContextSpecific ( tag_number ) => Ok ( Self {
58
+ tag_number ,
59
+ value : Any :: from_der ( any . as_bytes ( ) ) ? ,
60
+ } ) ,
61
+ actual => Err ( ErrorKind :: UnexpectedTag {
91
62
expected : None ,
92
- actual : any . tag ( ) ,
63
+ actual,
93
64
}
94
- . into ( ) ) ;
95
- } ;
96
-
97
- let value = Any :: from_der ( any. as_bytes ( ) ) ?;
98
-
99
- Self :: new ( tag, value)
65
+ . into ( ) ) ,
66
+ }
100
67
}
101
68
}
102
69
@@ -113,11 +80,9 @@ mod tests {
113
80
#[ test]
114
81
fn round_trip ( ) {
115
82
let field = ContextSpecific :: from_der ( EXAMPLE_BYTES ) . unwrap ( ) ;
116
- assert_eq ! ( field. tag( ) , 1 ) ;
117
-
118
- let value = field. value ( ) ;
119
- assert_eq ! ( value. tag( ) , Tag :: BitString ) ;
120
- assert_eq ! ( value. as_bytes( ) , & EXAMPLE_BYTES [ 5 ..] ) ;
83
+ assert_eq ! ( field. tag_number. value( ) , 1 ) ;
84
+ assert_eq ! ( field. value. tag( ) , Tag :: BitString ) ;
85
+ assert_eq ! ( field. value. as_bytes( ) , & EXAMPLE_BYTES [ 5 ..] ) ;
121
86
122
87
let mut buf = [ 0u8 ; 128 ] ;
123
88
let encoded = field. encode_to_slice ( & mut buf) . unwrap ( ) ;
0 commit comments