rasn/jer/
de.rs

1//! # Decoding JER
2
3use jzon::JsonValue;
4
5use crate::{
6    de::Error,
7    error::*,
8    types::{fields::Fields, *},
9    Decode,
10};
11
12macro_rules! decode_jer_value {
13    ($decoder_fn:expr, $input:expr) => {
14        $input
15            .pop()
16            .ok_or_else(|| DecodeError::from(JerDecodeErrorKind::eoi()))
17            .and_then($decoder_fn)
18    };
19}
20
21pub struct Decoder {
22    stack: alloc::vec::Vec<JsonValue>,
23}
24
25impl Decoder {
26    pub fn new(input: &str) -> Result<Self, <Decoder as crate::de::Decoder>::Error> {
27        let root = jzon::parse(input).map_err(|e| {
28            DecodeError::parser_fail(
29                alloc::format!("Error parsing JER JSON {e:?}"),
30                crate::Codec::Jer,
31            )
32        })?;
33        Ok(Self {
34            stack: alloc::vec![root],
35        })
36    }
37}
38
39impl From<JsonValue> for Decoder {
40    fn from(value: JsonValue) -> Self {
41        Self {
42            stack: alloc::vec![value],
43        }
44    }
45}
46
47impl crate::Decoder for Decoder {
48    type Error = DecodeError;
49
50    fn decode_any(&mut self) -> Result<Any, Self::Error> {
51        decode_jer_value!(Self::any_from_value, self.stack)
52    }
53
54    fn decode_bit_string(
55        &mut self,
56        _t: crate::Tag,
57        constraints: Constraints,
58    ) -> Result<BitString, Self::Error> {
59        let (mut padded, bitstring_length) = if let Some(size) = constraints
60            .size()
61            .and_then(|s| s.constraint.is_fixed().then_some(s.constraint.as_start()))
62            .flatten()
63        {
64            let value = BitString::try_from_vec(decode_jer_value!(
65                Self::octet_string_from_value,
66                self.stack
67            )?)
68            .map_err(|e| {
69                DecodeError::custom(
70                    alloc::format!("Failed to create BitString from bytes: {e:02x?}"),
71                    self.codec(),
72                )
73            })?;
74            (value, *size)
75        } else {
76            let last = self.stack.pop().ok_or_else(JerDecodeErrorKind::eoi)?;
77            let value_map = last
78                .as_object()
79                .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
80                    needed: "object",
81                    found: "unknown".into(),
82                })?;
83            let (value, length) = value_map
84                .get("value")
85                .and_then(|v| v.as_str())
86                .zip(value_map.get("length").and_then(|l| l.as_usize()))
87                .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
88                    needed: "JSON object containing 'value' and 'length' properties.",
89                    found: alloc::format!("{value_map:#?}"),
90                })?;
91            (
92                (0..value.len())
93                    .step_by(2)
94                    .map(|i| u8::from_str_radix(&value[i..=i + 1], 16))
95                    .collect::<Result<BitString, _>>()
96                    .map_err(|e| JerDecodeErrorKind::InvalidJerBitstring { parse_int_err: e })?,
97                length,
98            )
99        };
100        let padding_length = if bitstring_length % 8 == 0 {
101            0
102        } else {
103            8 - (bitstring_length % 8)
104        };
105        for _ in 0..padding_length {
106            padded.pop();
107        }
108        Ok(padded)
109    }
110
111    fn decode_bool(&mut self, _t: crate::Tag) -> Result<bool, Self::Error> {
112        decode_jer_value!(Self::boolean_from_value, self.stack)
113    }
114
115    fn decode_enumerated<E: Enumerated>(&mut self, _t: crate::Tag) -> Result<E, Self::Error> {
116        decode_jer_value!(Self::enumerated_from_value, self.stack)
117    }
118
119    fn decode_integer<I: crate::types::IntegerType>(
120        &mut self,
121        _t: crate::Tag,
122        _c: Constraints,
123    ) -> Result<I, Self::Error> {
124        decode_jer_value!(Self::integer_from_value::<I>, self.stack)
125    }
126
127    fn decode_null(&mut self, _t: crate::Tag) -> Result<(), Self::Error> {
128        decode_jer_value!(Self::null_from_value, self.stack)
129    }
130
131    fn decode_object_identifier(
132        &mut self,
133        _t: crate::Tag,
134    ) -> Result<ObjectIdentifier, Self::Error> {
135        decode_jer_value!(Self::object_identifier_from_value, self.stack)
136    }
137
138    fn decode_sequence<D, DF, F>(
139        &mut self,
140        _: crate::Tag,
141        _: Option<DF>,
142        decode_fn: F,
143    ) -> Result<D, Self::Error>
144    where
145        D: Constructed,
146        F: FnOnce(&mut Self) -> Result<D, Self::Error>,
147    {
148        let mut last = self.stack.pop().ok_or_else(JerDecodeErrorKind::eoi)?;
149        let value_map = last
150            .as_object_mut()
151            .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
152                needed: "object",
153                found: "unknown".into(),
154            })?;
155        let mut field_names = [D::FIELDS, D::EXTENDED_FIELDS.unwrap_or(Fields::empty())]
156            .iter()
157            .flat_map(|f| f.iter())
158            .map(|f| f.name)
159            .collect::<alloc::vec::Vec<&str>>();
160        field_names.reverse();
161        for name in field_names {
162            self.stack
163                .push(value_map.remove(name).unwrap_or(JsonValue::Null));
164        }
165
166        (decode_fn)(self)
167    }
168
169    fn decode_sequence_of<D: crate::Decode>(
170        &mut self,
171        _t: crate::Tag,
172        _c: Constraints,
173    ) -> Result<SequenceOf<D>, Self::Error> {
174        decode_jer_value!(|v| self.sequence_of_from_value(v), self.stack)
175    }
176
177    fn decode_set_of<D: crate::Decode + Ord>(
178        &mut self,
179        _t: crate::Tag,
180        _c: Constraints,
181    ) -> Result<SetOf<D>, Self::Error> {
182        decode_jer_value!(|v| self.set_of_from_value(v), self.stack)
183    }
184
185    fn decode_octet_string(
186        &mut self,
187        _t: crate::Tag,
188        _c: Constraints,
189    ) -> Result<alloc::vec::Vec<u8>, Self::Error> {
190        decode_jer_value!(Self::octet_string_from_value, self.stack)
191    }
192
193    fn decode_utf8_string(
194        &mut self,
195        _t: crate::Tag,
196        _c: Constraints,
197    ) -> Result<Utf8String, Self::Error> {
198        decode_jer_value!(Self::string_from_value, self.stack)
199    }
200
201    fn decode_visible_string(
202        &mut self,
203        _t: crate::Tag,
204        _c: Constraints,
205    ) -> Result<VisibleString, Self::Error> {
206        decode_jer_value!(Self::string_from_value, self.stack)?
207            .try_into()
208            .map_err(|e| {
209                DecodeError::string_conversion_failed(
210                    Tag::VISIBLE_STRING,
211                    alloc::format!("Error transforming VisibleString: {e:?}"),
212                    crate::Codec::Jer,
213                )
214            })
215    }
216
217    fn decode_general_string(
218        &mut self,
219        _t: crate::Tag,
220        _c: Constraints,
221    ) -> Result<GeneralString, Self::Error> {
222        decode_jer_value!(Self::string_from_value, self.stack)?
223            .try_into()
224            .map_err(|e| {
225                DecodeError::string_conversion_failed(
226                    Tag::GENERAL_STRING,
227                    alloc::format!("Error transforming GeneralString: {e:?}"),
228                    crate::Codec::Jer,
229                )
230            })
231    }
232
233    fn decode_ia5_string(
234        &mut self,
235        _t: crate::Tag,
236        _c: Constraints,
237    ) -> Result<Ia5String, Self::Error> {
238        decode_jer_value!(Self::string_from_value, self.stack)?
239            .try_into()
240            .map_err(|e| {
241                DecodeError::string_conversion_failed(
242                    Tag::IA5_STRING,
243                    alloc::format!("Error transforming IA5String: {e:?}"),
244                    crate::Codec::Jer,
245                )
246            })
247    }
248
249    fn decode_printable_string(
250        &mut self,
251        _t: crate::Tag,
252        _c: Constraints,
253    ) -> Result<PrintableString, Self::Error> {
254        decode_jer_value!(Self::string_from_value, self.stack)?
255            .try_into()
256            .map_err(|e| {
257                DecodeError::string_conversion_failed(
258                    Tag::PRINTABLE_STRING,
259                    alloc::format!("Error transforming PrintableString: {e:?}"),
260                    crate::Codec::Jer,
261                )
262            })
263    }
264
265    fn decode_numeric_string(
266        &mut self,
267        _t: crate::Tag,
268        _c: Constraints,
269    ) -> Result<NumericString, Self::Error> {
270        decode_jer_value!(Self::string_from_value, self.stack)?
271            .try_into()
272            .map_err(|e| {
273                DecodeError::string_conversion_failed(
274                    Tag::NUMERIC_STRING,
275                    alloc::format!("Error transforming NumericString: {e:?}"),
276                    crate::Codec::Jer,
277                )
278            })
279    }
280
281    fn decode_teletex_string(
282        &mut self,
283        _t: crate::Tag,
284        _c: Constraints,
285    ) -> Result<TeletexString, Self::Error> {
286        todo!()
287    }
288
289    fn decode_bmp_string(
290        &mut self,
291        _t: crate::Tag,
292        _c: Constraints,
293    ) -> Result<BmpString, Self::Error> {
294        decode_jer_value!(Self::string_from_value, self.stack)?
295            .try_into()
296            .map_err(|e| {
297                DecodeError::string_conversion_failed(
298                    Tag::BMP_STRING,
299                    alloc::format!("Error transforming BMPString: {e:?}"),
300                    crate::Codec::Jer,
301                )
302            })
303    }
304
305    fn decode_explicit_prefix<D: crate::Decode>(
306        &mut self,
307        _t: crate::Tag,
308    ) -> Result<D, Self::Error> {
309        D::decode(self)
310    }
311
312    fn decode_utc_time(&mut self, _t: crate::Tag) -> Result<UtcTime, Self::Error> {
313        decode_jer_value!(Self::utc_time_from_value, self.stack)
314    }
315
316    fn decode_generalized_time(&mut self, _t: crate::Tag) -> Result<GeneralizedTime, Self::Error> {
317        decode_jer_value!(Self::general_time_from_value, self.stack)
318    }
319
320    fn decode_set<FIELDS, SET, D, F>(
321        &mut self,
322        _t: crate::Tag,
323        decode_fn: D,
324        field_fn: F,
325    ) -> Result<SET, Self::Error>
326    where
327        SET: crate::Decode + Constructed,
328        FIELDS: crate::Decode,
329        D: Fn(&mut Self, usize, crate::Tag) -> Result<FIELDS, Self::Error>,
330        F: FnOnce(alloc::vec::Vec<FIELDS>) -> Result<SET, Self::Error>,
331    {
332        let mut last = self.stack.pop().ok_or_else(JerDecodeErrorKind::eoi)?;
333        let value_map = last
334            .as_object_mut()
335            .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
336                needed: "object",
337                found: "unknown".into(),
338            })?;
339        let mut field_indices = SET::FIELDS
340            .iter()
341            .enumerate()
342            .collect::<alloc::vec::Vec<_>>();
343        let mut fields = alloc::vec![];
344        field_indices
345            .sort_by(|(_, a), (_, b)| a.tag_tree.smallest_tag().cmp(&b.tag_tree.smallest_tag()));
346        for (index, field) in field_indices.into_iter() {
347            self.stack
348                .push(value_map.remove(field.name).unwrap_or(JsonValue::Null));
349            fields.push((decode_fn)(self, index, field.tag)?);
350        }
351
352        for (index, field) in SET::EXTENDED_FIELDS
353            .iter()
354            .flat_map(|fields| fields.iter())
355            .enumerate()
356        {
357            self.stack
358                .push(value_map.remove(field.name).unwrap_or(JsonValue::Null));
359            fields.push((decode_fn)(self, index + SET::FIELDS.len(), field.tag)?)
360        }
361
362        (field_fn)(fields)
363    }
364
365    fn decode_choice<D>(&mut self, _c: Constraints) -> Result<D, Self::Error>
366    where
367        D: DecodeChoice,
368    {
369        decode_jer_value!(|v| self.choice_from_value::<D>(v), self.stack)
370    }
371
372    fn decode_optional<D: crate::Decode>(&mut self) -> Result<Option<D>, Self::Error> {
373        let last = self.stack.pop().ok_or_else(JerDecodeErrorKind::eoi)?;
374        match last {
375            JsonValue::Null => Ok(None),
376            v => {
377                self.stack.push(v);
378                Some(D::decode(self)).transpose()
379            }
380        }
381    }
382
383    fn decode_optional_with_tag<D: crate::Decode>(
384        &mut self,
385        _: crate::Tag,
386    ) -> Result<Option<D>, Self::Error> {
387        self.decode_optional()
388    }
389
390    fn decode_optional_with_constraints<D: crate::Decode>(
391        &mut self,
392        _: Constraints,
393    ) -> Result<Option<D>, Self::Error> {
394        self.decode_optional()
395    }
396
397    fn decode_optional_with_tag_and_constraints<D: crate::Decode>(
398        &mut self,
399        _t: crate::Tag,
400        _c: Constraints,
401    ) -> Result<Option<D>, Self::Error> {
402        self.decode_optional()
403    }
404
405    fn decode_extension_addition_with_constraints<D>(
406        &mut self,
407        _: Constraints,
408    ) -> Result<Option<D>, Self::Error>
409    where
410        D: crate::Decode,
411    {
412        self.decode_optional()
413    }
414
415    fn decode_extension_addition_group<D: crate::Decode + Constructed>(
416        &mut self,
417    ) -> Result<Option<D>, Self::Error> {
418        self.decode_optional()
419    }
420
421    fn codec(&self) -> crate::Codec {
422        crate::Codec::Jer
423    }
424}
425
426// -------------------------------------------------------------------
427//
428//                        HELPER METHODS
429//
430// -------------------------------------------------------------------
431
432impl Decoder {
433    fn any_from_value(value: JsonValue) -> Result<Any, <Self as crate::de::Decoder>::Error> {
434        Ok(Any::new(alloc::format!("{value}").as_bytes().to_vec()))
435    }
436
437    fn boolean_from_value(value: JsonValue) -> Result<bool, DecodeError> {
438        Ok(value
439            .as_bool()
440            .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
441                needed: "boolean",
442                found: alloc::format!("{value}"),
443            })?)
444    }
445
446    fn enumerated_from_value<E: Enumerated>(value: JsonValue) -> Result<E, DecodeError> {
447        let identifier = value
448            .as_str()
449            .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
450                needed: "enumerated item as string",
451                found: alloc::format!("{value}"),
452            })?;
453        Ok(E::from_identifier(identifier).ok_or_else(|| {
454            JerDecodeErrorKind::InvalidEnumDiscriminant {
455                discriminant: alloc::string::String::from(identifier),
456            }
457        })?)
458    }
459
460    fn integer_from_value<I: crate::types::IntegerType>(
461        value: JsonValue,
462    ) -> Result<I, DecodeError> {
463        value
464            .as_i64()
465            .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
466                needed: "number (supported range -2^63..2^63)",
467                found: alloc::format!("{value}"),
468            })?
469            .try_into()
470            .map_err(|_| DecodeError::integer_overflow(I::WIDTH, crate::Codec::Jer))
471    }
472
473    fn null_from_value(value: JsonValue) -> Result<(), DecodeError> {
474        Ok(value
475            .is_null()
476            .then_some(())
477            .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
478                needed: "null",
479                found: alloc::format!("{value}"),
480            })?)
481    }
482
483    fn object_identifier_from_value(value: JsonValue) -> Result<ObjectIdentifier, DecodeError> {
484        // For performance reasons, sometimes it is better to use lazy one
485        #[allow(clippy::unnecessary_lazy_evaluations)]
486        Ok(value
487            .as_str()
488            .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
489                needed: "number array",
490                found: alloc::format!("{value}"),
491            })?
492            .split('.')
493            .map(|arc| {
494                arc.parse::<u32>()
495                    .map_err(|_| JerDecodeErrorKind::TypeMismatch {
496                        needed: "OID arc number",
497                        found: arc.into(),
498                    })
499            })
500            .collect::<Result<alloc::vec::Vec<u32>, _>>()
501            .ok()
502            .and_then(|arcs| Oid::new(&arcs).map(ObjectIdentifier::from))
503            .ok_or_else(|| JerDecodeErrorKind::InvalidOIDString { value })?)
504    }
505
506    fn sequence_of_from_value<D: Decode>(
507        &mut self,
508        value: JsonValue,
509    ) -> Result<SequenceOf<D>, DecodeError> {
510        value
511            .as_array()
512            .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
513                needed: "array",
514                found: alloc::format!("{value}"),
515            })?
516            .clone()
517            .into_iter()
518            .map(|v| {
519                self.stack.push(v);
520                D::decode(self)
521            })
522            .collect()
523    }
524
525    fn set_of_from_value<D: Decode + Ord>(
526        &mut self,
527        value: JsonValue,
528    ) -> Result<SetOf<D>, DecodeError> {
529        value
530            .as_array()
531            .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
532                needed: "array",
533                found: alloc::format!("{value}"),
534            })?
535            .clone()
536            .into_iter()
537            .try_fold(SetOf::new(), |mut acc, v| {
538                self.stack.push(v);
539                acc.insert(D::decode(self)?);
540                Ok(acc)
541            })
542    }
543
544    fn string_from_value(value: JsonValue) -> Result<alloc::string::String, DecodeError> {
545        Ok(value
546            .as_str()
547            .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
548                needed: "string",
549                found: alloc::format!("{value}"),
550            })
551            .map(|n| n.into())?)
552    }
553
554    fn choice_from_value<D>(&mut self, value: JsonValue) -> Result<D, DecodeError>
555    where
556        D: DecodeChoice,
557    {
558        let tag = value
559            .as_object()
560            .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
561                needed: "object",
562                found: alloc::format!("{value}"),
563            })?
564            .iter()
565            .next()
566            .and_then(|(k, v)| {
567                D::IDENTIFIERS
568                    .iter()
569                    .enumerate()
570                    .find(|id| id.1.eq_ignore_ascii_case(k))
571                    .map(|(i, _)| (i, v))
572            })
573            .map_or(Tag::EOC, |(i, v)| {
574                match variants::Variants::from_slice(
575                    &[D::VARIANTS, D::EXTENDED_VARIANTS.unwrap_or(&[])].concat(),
576                )
577                .get(i)
578                {
579                    Some(t) => {
580                        self.stack.push(v.clone());
581                        *t
582                    }
583                    None => Tag::EOC,
584                }
585            });
586        D::from_tag(self, tag)
587    }
588
589    fn octet_string_from_value(value: JsonValue) -> Result<alloc::vec::Vec<u8>, DecodeError> {
590        let octet_string = value
591            .as_str()
592            .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
593                needed: "hex string",
594                found: alloc::format!("{value}"),
595            })?;
596        Ok((0..octet_string.len())
597            .step_by(2)
598            .map(|i| u8::from_str_radix(&octet_string[i..=i + 1], 16))
599            .collect::<Result<alloc::vec::Vec<u8>, _>>()
600            .map_err(|_| JerDecodeErrorKind::InvalidJerOctetString {})?)
601    }
602
603    fn utc_time_from_value(value: JsonValue) -> Result<chrono::DateTime<chrono::Utc>, DecodeError> {
604        crate::ber::de::Decoder::parse_any_utc_time_string(
605            value
606                .as_str()
607                .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
608                    needed: "time string",
609                    found: alloc::format!("{value}"),
610                })?
611                .into(),
612        )
613    }
614
615    fn general_time_from_value(
616        value: JsonValue,
617    ) -> Result<chrono::DateTime<chrono::FixedOffset>, DecodeError> {
618        crate::ber::de::Decoder::parse_any_generalized_time_string(
619            value
620                .as_str()
621                .ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
622                    needed: "time string",
623                    found: alloc::format!("{value}"),
624                })?
625                .into(),
626        )
627    }
628}