1use crate::{
4 asn1::Any, Choice, Decodable, DecodeValue, Decoder, DerOrd, Encodable, EncodeValue, Encoder,
5 Error, Header, Length, Result, Tag, TagMode, TagNumber, Tagged, ValueOrd,
6};
7use core::cmp::Ordering;
8
9#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
14pub struct ContextSpecific<T> {
15 pub tag_number: TagNumber,
18
19 pub tag_mode: TagMode,
21
22 pub value: T,
24}
25
26impl<T> ContextSpecific<T> {
27 pub fn decode_explicit<'a>(
43 decoder: &mut Decoder<'a>,
44 tag_number: TagNumber,
45 ) -> Result<Option<Self>>
46 where
47 T: Decodable<'a>,
48 {
49 Self::decode_with(decoder, tag_number, |decoder| {
50 let any = Any::decode(decoder)?;
51
52 if !any.tag().is_constructed() {
53 return Err(any.tag().non_canonical_error());
54 }
55
56 Self::try_from(any)
57 })
58 }
59
60 pub fn decode_implicit<'a>(
67 decoder: &mut Decoder<'a>,
68 tag_number: TagNumber,
69 ) -> Result<Option<Self>>
70 where
71 T: DecodeValue<'a> + Tagged,
72 {
73 Self::decode_with(decoder, tag_number, |decoder| {
74 let header = Header::decode(decoder)?;
75 let value = T::decode_value(decoder, header.length)?;
76
77 if header.tag.is_constructed() != value.tag().is_constructed() {
78 return Err(header.tag.non_canonical_error());
79 }
80
81 Ok(Self {
82 tag_number,
83 tag_mode: TagMode::Implicit,
84 value,
85 })
86 })
87 }
88
89 fn decode_with<'a, F>(
92 decoder: &mut Decoder<'a>,
93 tag_number: TagNumber,
94 f: F,
95 ) -> Result<Option<Self>>
96 where
97 F: FnOnce(&mut Decoder<'a>) -> Result<Self>,
98 {
99 while let Some(octet) = decoder.peek_byte() {
100 let tag = Tag::try_from(octet)?;
101
102 if !tag.is_context_specific() || (tag.number() > tag_number) {
103 break;
104 } else if tag.number() == tag_number {
105 return Some(f(decoder)).transpose();
106 } else {
107 decoder.any()?;
108 }
109 }
110
111 Ok(None)
112 }
113
114 pub fn to_ref(&self) -> ContextSpecificRef<'_, T> {
116 ContextSpecificRef {
117 tag_number: self.tag_number,
118 tag_mode: self.tag_mode,
119 value: &self.value,
120 }
121 }
122}
123
124impl<'a, T> Choice<'a> for ContextSpecific<T>
125where
126 T: Decodable<'a> + Tagged,
127{
128 fn can_decode(tag: Tag) -> bool {
129 tag.is_context_specific()
130 }
131}
132
133impl<'a, T> Decodable<'a> for ContextSpecific<T>
134where
135 T: Decodable<'a>,
136{
137 fn decode(decoder: &mut Decoder<'a>) -> Result<Self> {
138 Any::decode(decoder)?.try_into()
139 }
140}
141
142impl<T> EncodeValue for ContextSpecific<T>
143where
144 T: EncodeValue + Tagged,
145{
146 fn value_len(&self) -> Result<Length> {
147 self.to_ref().value_len()
148 }
149
150 fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> {
151 self.to_ref().encode_value(encoder)
152 }
153}
154
155impl<T> Tagged for ContextSpecific<T>
156where
157 T: Tagged,
158{
159 fn tag(&self) -> Tag {
160 self.to_ref().tag()
161 }
162}
163
164impl<T> ValueOrd for ContextSpecific<T>
165where
166 T: EncodeValue + ValueOrd + Tagged,
167{
168 fn value_cmp(&self, other: &Self) -> Result<Ordering> {
169 self.to_ref().value_cmp(&other.to_ref())
170 }
171}
172
173impl<'a, T> TryFrom<Any<'a>> for ContextSpecific<T>
174where
175 T: Decodable<'a>,
176{
177 type Error = Error;
178
179 fn try_from(any: Any<'a>) -> Result<ContextSpecific<T>> {
180 match any.tag() {
181 Tag::ContextSpecific {
182 number,
183 constructed: true,
184 } => Ok(Self {
185 tag_number: number,
186 tag_mode: TagMode::default(),
187 value: T::from_der(any.value())?,
188 }),
189 tag => Err(tag.unexpected_error(None)),
190 }
191 }
192}
193
194#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
199pub struct ContextSpecificRef<'a, T> {
200 pub tag_number: TagNumber,
203
204 pub tag_mode: TagMode,
206
207 pub value: &'a T,
209}
210
211impl<T> EncodeValue for ContextSpecificRef<'_, T>
212where
213 T: EncodeValue + Tagged,
214{
215 fn value_len(&self) -> Result<Length> {
216 match self.tag_mode {
217 TagMode::Explicit => self.value.encoded_len(),
218 TagMode::Implicit => self.value.value_len(),
219 }
220 }
221
222 fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> {
223 match self.tag_mode {
224 TagMode::Explicit => self.value.encode(encoder),
225 TagMode::Implicit => self.value.encode_value(encoder),
226 }
227 }
228}
229
230impl<T> Tagged for ContextSpecificRef<'_, T>
231where
232 T: Tagged,
233{
234 fn tag(&self) -> Tag {
235 let constructed = match self.tag_mode {
236 TagMode::Explicit => true,
237 TagMode::Implicit => self.value.tag().is_constructed(),
238 };
239
240 Tag::ContextSpecific {
241 number: self.tag_number,
242 constructed,
243 }
244 }
245}
246
247impl<T> ValueOrd for ContextSpecificRef<'_, T>
248where
249 T: EncodeValue + ValueOrd + Tagged,
250{
251 fn value_cmp(&self, other: &Self) -> Result<Ordering> {
252 match self.tag_mode {
253 TagMode::Explicit => self.der_cmp(other),
254 TagMode::Implicit => self.value_cmp(other),
255 }
256 }
257}
258
259#[cfg(test)]
260mod tests {
261 use super::ContextSpecific;
262 use crate::{asn1::BitString, Decodable, Decoder, Encodable, TagMode, TagNumber};
263 use hex_literal::hex;
264
265 const EXAMPLE_BYTES: &[u8] =
267 &hex!("A123032100A3A7EAE3A8373830BC47E1167BC50E1DB551999651E0E2DC587623438EAC3F31");
268
269 #[test]
270 fn round_trip() {
271 let field = ContextSpecific::<BitString<'_>>::from_der(EXAMPLE_BYTES).unwrap();
272 assert_eq!(field.tag_number.value(), 1);
273 assert_eq!(
274 field.value,
275 BitString::from_bytes(&EXAMPLE_BYTES[5..]).unwrap()
276 );
277
278 let mut buf = [0u8; 128];
279 let encoded = field.encode_to_slice(&mut buf).unwrap();
280 assert_eq!(encoded, EXAMPLE_BYTES);
281 }
282
283 #[test]
284 fn context_specific_with_explicit_field() {
285 let tag_number = TagNumber::new(0);
286
287 let mut decoder = Decoder::new(&[]).unwrap();
289 assert_eq!(
290 ContextSpecific::<u8>::decode_explicit(&mut decoder, tag_number).unwrap(),
291 None
292 );
293
294 let mut decoder = Decoder::new(&hex!("020100")).unwrap();
296 assert_eq!(
297 ContextSpecific::<u8>::decode_explicit(&mut decoder, tag_number).unwrap(),
298 None
299 );
300
301 let mut decoder = Decoder::new(&hex!("A003020100")).unwrap();
303 let field = ContextSpecific::<u8>::decode_explicit(&mut decoder, tag_number)
304 .unwrap()
305 .unwrap();
306
307 assert_eq!(field.tag_number, tag_number);
308 assert_eq!(field.tag_mode, TagMode::Explicit);
309 assert_eq!(field.value, 0);
310 }
311
312 #[test]
313 fn context_specific_with_implicit_field() {
314 let context_specific_implicit_bytes =
321 hex!("81210019BF44096984CDFE8541BAC167DC3B96C85086AA30B6B6CB0C5C38AD703166E1");
322
323 let tag_number = TagNumber::new(1);
324
325 let mut decoder = Decoder::new(&context_specific_implicit_bytes).unwrap();
326 let field = ContextSpecific::<BitString<'_>>::decode_implicit(&mut decoder, tag_number)
327 .unwrap()
328 .unwrap();
329
330 assert_eq!(field.tag_number, tag_number);
331 assert_eq!(field.tag_mode, TagMode::Implicit);
332 assert_eq!(
333 field.value.as_bytes().unwrap(),
334 &context_specific_implicit_bytes[3..]
335 );
336 }
337
338 #[test]
339 fn context_specific_skipping_unknown_field() {
340 let tag = TagNumber::new(1);
341 let mut decoder = Decoder::new(&hex!("A003020100A103020101")).unwrap();
342 let field = ContextSpecific::<u8>::decode_explicit(&mut decoder, tag)
343 .unwrap()
344 .unwrap();
345 assert_eq!(field.value, 1);
346 }
347
348 #[test]
349 fn context_specific_returns_none_on_greater_tag_number() {
350 let tag = TagNumber::new(0);
351 let mut decoder = Decoder::new(&hex!("A103020101")).unwrap();
352 assert_eq!(
353 ContextSpecific::<u8>::decode_explicit(&mut decoder, tag).unwrap(),
354 None
355 );
356 }
357}