1
1
//! Context-specific field.
2
2
3
3
use crate :: {
4
- Choice , Decode , DecodeValue , DerOrd , Encode , EncodeValue , EncodeValueRef , Error , Header ,
4
+ Choice , Class , Decode , DecodeValue , DerOrd , Encode , EncodeValue , EncodeValueRef , Error , Header ,
5
5
Length , Reader , Tag , TagMode , TagNumber , Tagged , ValueOrd , Writer , asn1:: AnyRef ,
6
6
} ;
7
7
use core:: cmp:: Ordering ;
@@ -46,7 +46,9 @@ impl<T> ContextSpecific<T> {
46
46
where
47
47
T : Decode < ' a > ,
48
48
{
49
- Self :: decode_with ( reader, tag_number, |reader| Self :: decode ( reader) )
49
+ peek_decode_optional ( reader, Class :: ContextSpecific , tag_number, |reader| {
50
+ Self :: decode ( reader)
51
+ } )
50
52
}
51
53
52
54
/// Attempt to decode an `IMPLICIT` ASN.1 `CONTEXT-SPECIFIC` field with the
@@ -62,45 +64,50 @@ impl<T> ContextSpecific<T> {
62
64
where
63
65
T : DecodeValue < ' a > + Tagged ,
64
66
{
65
- Self :: decode_with :: < _ , _ , T :: Error > ( reader, tag_number, |reader| {
66
- let header = Header :: decode ( reader) ?;
67
- let value = T :: decode_value ( reader, header) ?;
68
-
69
- if header. tag . is_constructed ( ) != value. tag ( ) . is_constructed ( ) {
70
- return Err ( header. tag . non_canonical_error ( ) . into ( ) ) ;
71
- }
72
-
73
- Ok ( Self {
74
- tag_number,
75
- tag_mode : TagMode :: Implicit ,
76
- value,
77
- } )
78
- } )
67
+ peek_decode_optional :: < Self , _ , _ , T :: Error > (
68
+ reader,
69
+ Class :: ContextSpecific ,
70
+ tag_number,
71
+ |reader| {
72
+ let header = Header :: decode ( reader) ?;
73
+ let value = T :: decode_value ( reader, header) ?;
74
+
75
+ if header. tag . is_constructed ( ) != value. tag ( ) . is_constructed ( ) {
76
+ return Err ( header. tag . non_canonical_error ( ) . into ( ) ) ;
77
+ }
78
+
79
+ Ok ( Self {
80
+ tag_number,
81
+ tag_mode : TagMode :: Implicit ,
82
+ value,
83
+ } )
84
+ } ,
85
+ )
79
86
}
87
+ }
80
88
81
- /// Attempt to decode a context-specific field with the given
82
- /// helper callback.
83
- fn decode_with < ' a , F , R : Reader < ' a > , E > (
84
- reader : & mut R ,
85
- tag_number : TagNumber ,
86
- f : F ,
87
- ) -> Result < Option < Self > , E >
88
- where
89
- F : FnOnce ( & mut R ) -> Result < Self , E > ,
90
- E : From < Error > ,
91
- {
92
- while let Some ( tag) = Tag :: peek_optional ( reader) ? {
93
- if !tag. is_context_specific ( ) || ( tag. number ( ) > tag_number) {
94
- break ;
95
- } else if tag. number ( ) == tag_number {
96
- return Some ( f ( reader) ) . transpose ( ) ;
97
- } else {
98
- AnyRef :: decode ( reader) ?;
99
- }
100
- }
101
-
102
- Ok ( None )
89
+ /// Attempt to decode a context-specific (or any given class) field
90
+ /// with the given helper callback.
91
+ fn peek_decode_optional < ' a , T , F , R : Reader < ' a > , E > (
92
+ reader : & mut R ,
93
+ class : Class ,
94
+ tag_number : TagNumber ,
95
+ f : F ,
96
+ ) -> Result < Option < T > , E >
97
+ where
98
+ F : FnOnce ( & mut R ) -> Result < T , E > ,
99
+ E : From < Error > ,
100
+ {
101
+ // Peek tag or ignore end of stream
102
+ let Some ( tag) = Tag :: peek_optional ( reader) ? else {
103
+ return Ok ( None ) ;
104
+ } ;
105
+ // Ignore tags with different numbers
106
+ if tag. class ( ) != class || tag. number ( ) != tag_number {
107
+ return Ok ( None ) ;
103
108
}
109
+ // Tag matches - callback reads tag and decodes value
110
+ Some ( f ( reader) ) . transpose ( )
104
111
}
105
112
106
113
impl < ' a , T > Choice < ' a > for ContextSpecific < T >
@@ -335,13 +342,11 @@ mod tests {
335
342
}
336
343
337
344
#[ test]
338
- fn context_specific_skipping_unknown_field ( ) {
345
+ fn context_specific_not_skipping_unknown_field ( ) {
339
346
let tag = TagNumber ( 1 ) ;
340
347
let mut reader = SliceReader :: new ( & hex ! ( "A003020100A103020101" ) ) . unwrap ( ) ;
341
- let field = ContextSpecific :: < u8 > :: decode_explicit ( & mut reader, tag)
342
- . unwrap ( )
343
- . unwrap ( ) ;
344
- assert_eq ! ( field. value, 1 ) ;
348
+ let field = ContextSpecific :: < u8 > :: decode_explicit ( & mut reader, tag) . unwrap ( ) ;
349
+ assert_eq ! ( field, None ) ;
345
350
}
346
351
347
352
#[ test]
0 commit comments