1use crate::{
4 Choice, Class, Decode, DecodeValue, DerOrd, Encode, EncodeValue, EncodeValueRef, Error, Header,
5 Length, Reader, Tag, TagMode, TagNumber, Tagged, ValueOrd, Writer, asn1::AnyRef,
6 tag::IsConstructed,
7};
8use core::cmp::Ordering;
9
10#[cfg(doc)]
11use crate::ErrorKind;
12
13impl_custom_class!(
14 ContextSpecific,
15 ContextSpecific,
16 "CONTEXT-SPECIFIC",
17 "0b10000000"
18);
19impl_custom_class_ref!(
20 ContextSpecificRef,
21 ContextSpecific,
22 "CONTEXT-SPECIFIC",
23 "0b10000000"
24);
25
26#[cfg(test)]
27#[allow(clippy::unwrap_used)]
28mod tests {
29 use super::ContextSpecific;
30 use crate::{Decode, Encode, SliceReader, TagMode, TagNumber, asn1::BitStringRef};
31 use hex_literal::hex;
32
33 #[cfg(feature = "heapless")]
34 use crate::asn1::{ContextSpecificRef, SetOf, Utf8StringRef};
35
36 const EXAMPLE_BYTES: &[u8] =
38 &hex!("A123032100A3A7EAE3A8373830BC47E1167BC50E1DB551999651E0E2DC587623438EAC3F31");
39
40 #[test]
41 fn round_trip() {
42 let field = ContextSpecific::<BitStringRef<'_>>::from_der(EXAMPLE_BYTES).unwrap();
43 assert_eq!(field.tag_number.value(), 1);
44 assert_eq!(
45 field.value,
46 BitStringRef::from_bytes(&EXAMPLE_BYTES[5..]).unwrap()
47 );
48
49 let mut buf = [0u8; 128];
50 let encoded = field.encode_to_slice(&mut buf).unwrap();
51 assert_eq!(encoded, EXAMPLE_BYTES);
52 }
53
54 #[test]
55 fn context_specific_with_explicit_field() {
56 let tag_number = TagNumber(0);
57
58 let mut reader = SliceReader::new(&[]).unwrap();
60 assert_eq!(
61 ContextSpecific::<u8>::decode_explicit(&mut reader, tag_number).unwrap(),
62 None
63 );
64
65 let mut reader = SliceReader::new(&hex!("020100")).unwrap();
67 assert_eq!(
68 ContextSpecific::<u8>::decode_explicit(&mut reader, tag_number).unwrap(),
69 None
70 );
71
72 let mut reader = SliceReader::new(&hex!("A003020100")).unwrap();
74 let field = ContextSpecific::<u8>::decode_explicit(&mut reader, tag_number)
75 .unwrap()
76 .unwrap();
77
78 assert_eq!(field.tag_number, tag_number);
79 assert_eq!(field.tag_mode, TagMode::Explicit);
80 assert_eq!(field.value, 0);
81 }
82
83 #[test]
84 fn context_specific_with_implicit_field() {
85 let context_specific_implicit_bytes =
92 hex!("81210019BF44096984CDFE8541BAC167DC3B96C85086AA30B6B6CB0C5C38AD703166E1");
93
94 let tag_number = TagNumber(1);
95
96 let mut reader = SliceReader::new(&context_specific_implicit_bytes).unwrap();
97 let field = ContextSpecific::<BitStringRef<'_>>::decode_implicit(&mut reader, tag_number)
98 .unwrap()
99 .unwrap();
100
101 assert_eq!(field.tag_number, tag_number);
102 assert_eq!(field.tag_mode, TagMode::Implicit);
103 assert_eq!(
104 field.value.as_bytes().unwrap(),
105 &context_specific_implicit_bytes[3..]
106 );
107 }
108
109 #[test]
110 fn context_specific_not_skipping_unknown_field() {
111 let tag = TagNumber(1);
112 let mut reader = SliceReader::new(&hex!("A003020100A103020101")).unwrap();
113 let field = ContextSpecific::<u8>::decode_explicit(&mut reader, tag).unwrap();
114 assert_eq!(field, None);
115 }
116
117 #[test]
118 fn context_specific_returns_none_on_greater_tag_number() {
119 let tag = TagNumber(0);
120 let mut reader = SliceReader::new(&hex!("A103020101")).unwrap();
121 assert_eq!(
122 ContextSpecific::<u8>::decode_explicit(&mut reader, tag).unwrap(),
123 None
124 );
125 }
126
127 #[test]
128 #[cfg(feature = "heapless")]
129 fn context_specific_explicit_ref() {
130 let mut set = SetOf::new();
131 set.insert(8u16).unwrap();
132 set.insert(7u16).unwrap();
133
134 let field = ContextSpecificRef::<SetOf<u16, 2>> {
135 value: &set,
136 tag_number: TagNumber(2),
137 tag_mode: TagMode::Explicit,
138 };
139
140 let mut buf = [0u8; 16];
141 let encoded = field.encode_to_slice(&mut buf).unwrap();
142 assert_eq!(
143 encoded,
144 &[
145 0xA2, 0x08, 0x31, 0x06,
146 0x02, 0x01, 0x07, 0x02, 0x01, 0x08
147 ]
148 );
149
150 let mut reader = SliceReader::new(encoded).unwrap();
151 let field = ContextSpecific::<SetOf<u16, 2>>::decode_explicit(&mut reader, TagNumber(2))
152 .unwrap()
153 .unwrap();
154
155 assert_eq!(field.value.len(), 2);
156 assert_eq!(field.value.get(0).cloned(), Some(7));
157 assert_eq!(field.value.get(1).cloned(), Some(8));
158 }
159
160 #[test]
161 #[cfg(feature = "heapless")]
162 fn context_specific_implicit_ref() {
163 let hello = Utf8StringRef::new("Hello").unwrap();
164 let world = Utf8StringRef::new("world").unwrap();
165
166 let mut set = SetOf::new();
167 set.insert(hello).unwrap();
168 set.insert(world).unwrap();
169
170 let field = ContextSpecificRef::<SetOf<Utf8StringRef<'_>, 2>> {
171 value: &set,
172 tag_number: TagNumber(2),
173 tag_mode: TagMode::Implicit,
174 };
175
176 let mut buf = [0u8; 16];
177 let encoded = field.encode_to_slice(&mut buf).unwrap();
178 assert_eq!(
179 encoded,
180 &[
181 0xA2, 0x0E, 0x0C, 0x05, b'H', b'e', b'l', b'l', b'o', 0x0C, 0x05, b'w', b'o', b'r', b'l', b'd', ]
185 );
186
187 let mut reader = SliceReader::new(encoded).unwrap();
188 let field = ContextSpecific::<SetOf<Utf8StringRef<'_>, 2>>::decode_implicit(
189 &mut reader,
190 TagNumber(2),
191 )
192 .unwrap()
193 .unwrap();
194
195 assert_eq!(field.value.len(), 2);
196 assert_eq!(field.value.get(0).cloned(), Some(hello));
197 assert_eq!(field.value.get(1).cloned(), Some(world));
198 }
199}