rasn/
xer.rs

1//! XML Encoding Rules.
2
3pub mod de;
4pub mod enc;
5
6const BOOLEAN_TRUE_TAG: &str = "true";
7const BOOLEAN_FALSE_TAG: &str = "false";
8const PLUS_INFINITY_TAG: &str = "PLUS-INFINITY";
9const MINUS_INFINITY_TAG: &str = "MINUS-INFINITY";
10const NAN_TAG: &str = "NOT-A-NUMBER";
11const PLUS_INFINITY_VALUE: &str = "INF";
12const MINUS_INFINITY_VALUE: &str = "-INF";
13const NAN_VALUE: &str = "NaN";
14
15/// Attempts to decode `T` from `input` using XER.
16/// # Errors
17/// Returns error specific to XER decoder if decoding is not possible.
18pub fn decode<T: crate::Decode>(input: &[u8]) -> Result<T, crate::error::DecodeError> {
19    T::decode(&mut de::Decoder::new(input)?)
20}
21
22/// Attempts to encode `value` to XER.
23/// # Errors
24/// Returns error specific to XER encoder if encoding is not possible.
25pub fn encode<T: crate::Encode>(
26    value: &T,
27) -> Result<alloc::vec::Vec<u8>, crate::error::EncodeError> {
28    let mut encoder = enc::Encoder::new();
29    value.encode(&mut encoder)?;
30    Ok(encoder.finish())
31}
32
33#[cfg(test)]
34mod tests {
35    use core::f64;
36
37    use bitvec::bitvec;
38    use bitvec::order::Msb0;
39
40    use crate::prelude::*;
41    use crate::xer::{decode, encode};
42
43    #[derive(AsnType, Debug, Encode, Decode, PartialEq)]
44    #[rasn(automatic_tags)]
45    #[rasn(crate_root = "crate")]
46    #[non_exhaustive]
47    struct NestedTestA {
48        wine: bool,
49        grappa: OctetString,
50        inner: InnerTestA,
51        #[rasn(extension_addition)]
52        oid: Option<ObjectIdentifier>,
53    }
54
55    #[derive(AsnType, Debug, Encode, Decode, PartialEq, Eq, Hash)]
56    #[rasn(automatic_tags)]
57    #[rasn(crate_root = "crate")]
58    struct InnerTestA {
59        hidden: Option<bool>,
60    }
61
62    #[derive(AsnType, Debug, Encode, Decode, Clone, PartialEq, Eq, Hash)]
63    #[rasn(automatic_tags)]
64    #[rasn(crate_root = "crate", identifier = "Enum-Sequence")]
65    struct EnumSequence {
66        #[rasn(identifier = "enum-field")]
67        enum_field: EnumType,
68    }
69
70    #[derive(AsnType, Debug, Encode, Decode, PartialEq)]
71    #[rasn(automatic_tags)]
72    #[rasn(crate_root = "crate", identifier = "Deep-Sequence")]
73    struct DeepSequence {
74        nested: NestedTestA,
75        recursion: RecursiveChoice,
76    }
77
78    #[derive(AsnType, Debug, Encode, Decode, PartialEq)]
79    #[rasn(automatic_tags)]
80    #[rasn(choice, crate_root = "crate")]
81    enum RecursiveChoice {
82        Leaf,
83        Fruit(bool),
84        Recursion(Box<RecursiveChoice>),
85    }
86
87    #[derive(AsnType, Debug, Encode, Decode, PartialEq)]
88    #[rasn(automatic_tags)]
89    #[rasn(crate_root = "crate")]
90    struct SequenceWithChoice {
91        recursion: RecursiveChoice,
92        nested: NestedTestA,
93    }
94
95    #[derive(AsnType, Debug, Encode, Decode, PartialEq, Copy, Clone, Eq, Hash)]
96    #[rasn(enumerated, automatic_tags)]
97    #[rasn(crate_root = "crate")]
98    enum EnumType {
99        #[rasn(identifier = "eins")]
100        First,
101        #[rasn(identifier = "zwei")]
102        Second,
103    }
104
105    #[derive(AsnType, Debug, Encode, Decode, PartialEq)]
106    #[rasn(choice, automatic_tags)]
107    #[rasn(crate_root = "crate")]
108    enum ChoiceType {
109        #[rasn(identifier = "enum")]
110        EnumVariant(EnumType),
111        #[allow(non_camel_case_types)]
112        nested(InnerTestA),
113    }
114
115    #[derive(AsnType, Debug, Encode, Decode, PartialEq)]
116    #[rasn(automatic_tags, delegate)]
117    #[rasn(crate_root = "crate")]
118    struct ChoiceDelegate(pub ChoiceType);
119
120    #[derive(AsnType, Debug, Encode, Decode, PartialEq)]
121    #[rasn(automatic_tags)]
122    #[rasn(crate_root = "crate")]
123    struct DefaultSequence {
124        #[rasn(identifier = "bool-df", default = "bool_default")]
125        bool_with_default: bool,
126        recursion: Vec<DefaultSequence>,
127    }
128
129    #[derive(AsnType, Debug, Encode, Decode, PartialEq)]
130    #[rasn(automatic_tags)]
131    #[rasn(crate_root = "crate")]
132    pub struct SequenceWithSequenceOf {
133        ids: SequenceOfIntegers,
134        flag: bool,
135        int: Integer,
136        enum_val: EnumType,
137    }
138
139    #[derive(AsnType, Debug, Encode, Decode, PartialEq)]
140    #[rasn(automatic_tags)]
141    #[rasn(crate_root = "crate")]
142    pub struct SequenceWithSetOf {
143        ids: SetOfIntegers,
144        flag: bool,
145        int: Integer,
146        enum_val: EnumType,
147    }
148
149    fn bool_default() -> bool {
150        bool::default()
151    }
152
153    type SequenceOfChoices = Vec<ChoiceType>;
154    type SequenceOfDelegateChoices = Vec<ChoiceDelegate>;
155    type SequenceOfEnumSequences = Vec<EnumSequence>;
156    type SequenceOfBitStrings = Vec<BitString>;
157    type SequenceOfEnums = Vec<EnumType>;
158    type SequenceOfNulls = Vec<()>;
159    type SequenceOfIntegers = Vec<i32>;
160    type SequenceOfSequenceOfSequences = Vec<Vec<InnerTestA>>;
161
162    type SetOfEnumSequences = SetOf<EnumSequence>;
163    type SetOfEnums = SetOf<EnumType>;
164    type SetOfBools = SetOf<bool>;
165    type SetOfIntegers = SetOf<i32>;
166    type SetOfSequenceOfSequences = SetOf<Vec<InnerTestA>>;
167
168    macro_rules! round_trip {
169        ($test_name:ident, $type:ident, $value:expr, $expected_ty:literal, $expected_val:literal) => {
170            #[test]
171            fn $test_name() {
172                #[derive(AsnType, Debug, Encode, Decode, PartialEq)]
173                #[rasn(automatic_tags, delegate)]
174                #[rasn(crate_root = "crate")]
175                struct DelegateType(pub $type);
176
177                #[derive(AsnType, Debug, Encode, Decode, PartialEq)]
178                #[rasn(automatic_tags, delegate)]
179                #[rasn(crate_root = "crate")]
180                struct NestedDelegateType(pub DelegateType);
181
182                #[derive(AsnType, Debug, Encode, Decode, PartialEq)]
183                #[rasn(automatic_tags, delegate, identifier = "Alias")]
184                #[rasn(crate_root = "crate")]
185                struct AliasDelegateType(pub $type);
186
187                let input = $value;
188                let encoded = String::from_utf8(encode(&input).unwrap()).unwrap();
189                let expected = String::from("<")
190                    + $expected_ty
191                    + ">"
192                    + $expected_val
193                    + "</"
194                    + $expected_ty
195                    + ">";
196                let decoded = decode::<$type>(expected.as_bytes()).unwrap();
197                assert_eq!(input, decoded);
198                assert_eq!(encoded, expected);
199
200                let input = DelegateType($value);
201                let encoded = String::from_utf8(encode(&input).unwrap()).unwrap();
202                let expected = String::from("<DelegateType>") + $expected_val + "</DelegateType>";
203                let decoded = decode::<DelegateType>(expected.as_bytes()).unwrap();
204                assert_eq!(input, decoded);
205                assert_eq!(encoded, expected);
206
207                let input = NestedDelegateType(DelegateType($value));
208                let encoded = String::from_utf8(encode(&input).unwrap()).unwrap();
209                let expected =
210                    String::from("<NestedDelegateType>") + $expected_val + "</NestedDelegateType>";
211                let decoded = decode::<NestedDelegateType>(expected.as_bytes()).unwrap();
212                assert_eq!(input, decoded);
213                assert_eq!(encoded, expected);
214
215                let input = AliasDelegateType($value);
216                let encoded = String::from_utf8(encode(&input).unwrap()).unwrap();
217                let expected = String::from("<Alias>") + $expected_val + "</Alias>";
218                let decoded = decode::<AliasDelegateType>(expected.as_bytes()).unwrap();
219                assert_eq!(input, decoded);
220                assert_eq!(encoded, expected);
221            }
222        };
223    }
224
225    round_trip!(boolean_true, bool, true, "BOOLEAN", "<true />");
226    round_trip!(boolean_false, bool, false, "BOOLEAN", "<false />");
227    round_trip!(integer_sml, Integer, Integer::from(1), "INTEGER", "1");
228    round_trip!(integer_neg, Integer, Integer::from(-2), "INTEGER", "-2");
229    round_trip!(integer_u8, u8, 212, "INTEGER", "212");
230    round_trip!(
231        integer_i64,
232        i64,
233        -2_141_247_653_269_i64,
234        "INTEGER",
235        "-2141247653269"
236    );
237    round_trip!(positive_real, f64, 1.1234, "REAL", "1.1234");
238    round_trip!(negative_real, f64, -1.1234, "REAL", "-1.1234");
239    round_trip!(
240        empty_element_infinity,
241        f64,
242        f64::INFINITY,
243        "REAL",
244        "<PLUS-INFINITY />"
245    );
246    round_trip!(
247        empty_element_neg_infinity,
248        f64,
249        f64::NEG_INFINITY,
250        "REAL",
251        "<MINUS-INFINITY />"
252    );
253    round_trip!(
254        bit_string,
255        BitString,
256        bitvec![u8, Msb0; 1,0,1,1,0,0,1],
257        "BIT_STRING",
258        "1011001"
259    );
260    round_trip!(
261        octet_string,
262        OctetString,
263        OctetString::from([255u8, 0, 8, 10].to_vec()),
264        "OCTET_STRING",
265        "FF00080A"
266    );
267    round_trip!(
268        ia5_string,
269        Ia5String,
270        Ia5String::from_iso646_bytes(&[0x30, 0x31, 0x32, 0x33, 0x34, 0x35]).unwrap(),
271        "IA5String",
272        "012345"
273    );
274    round_trip!(
275        numeric_string,
276        NumericString,
277        NumericString::from_bytes(&[0x30, 0x31, 0x32, 0x33, 0x34, 0x35]).unwrap(),
278        "NumericString",
279        "012345"
280    );
281    round_trip!(
282        utf8_string,
283        Utf8String,
284        "012345".to_string(),
285        "UTF8String",
286        "012345"
287    );
288    round_trip!(
289        object_identifier,
290        ObjectIdentifier,
291        ObjectIdentifier::from(Oid::const_new(&[1, 654, 2, 1])),
292        "OBJECT_IDENTIFIER",
293        "1.654.2.1"
294    );
295    round_trip!(
296        sequence,
297        InnerTestA,
298        InnerTestA {
299            hidden: Some(false)
300        },
301        "InnerTestA",
302        "<hidden><false /></hidden>"
303    );
304    round_trip!(
305        enumerated,
306        EnumType,
307        EnumType::First,
308        "EnumType",
309        "<eins />"
310    );
311    round_trip!(
312        choice,
313        ChoiceType,
314        ChoiceType::nested(InnerTestA { hidden: Some(true) }),
315        "ChoiceType",
316        "<nested><hidden><true /></hidden></nested>"
317    );
318    round_trip!(
319        choice_with_none_value,
320        ChoiceType,
321        ChoiceType::nested(InnerTestA { hidden: None }),
322        "ChoiceType",
323        "<nested />"
324    );
325    round_trip!(
326        enum_in_choice,
327        ChoiceType,
328        ChoiceType::EnumVariant(EnumType::Second),
329        "ChoiceType",
330        "<enum><zwei /></enum>"
331    );
332    round_trip!(
333        choice_recursion,
334        RecursiveChoice,
335        RecursiveChoice::Recursion(Box::new(RecursiveChoice::Recursion(Box::new(RecursiveChoice::Recursion(Box::new(RecursiveChoice::Recursion(Box::new(RecursiveChoice::Fruit(true))))))))),
336        "RecursiveChoice",
337        "<Recursion><Recursion><Recursion><Recursion><Fruit><true /></Fruit></Recursion></Recursion></Recursion></Recursion>"
338    );
339    round_trip!(
340        recursive_choice_eventually_empty,
341        RecursiveChoice,
342        RecursiveChoice::Recursion(Box::new(RecursiveChoice::Recursion(Box::new(RecursiveChoice::Recursion(Box::new(RecursiveChoice::Recursion(Box::new(RecursiveChoice::Leaf)))))))),
343        "RecursiveChoice",
344        "<Recursion><Recursion><Recursion><Recursion><Leaf /></Recursion></Recursion></Recursion></Recursion>"
345    );
346    round_trip!(
347        deep_sequence,
348        DeepSequence,
349        DeepSequence { nested: NestedTestA { wine: true, grappa: vec![0, 1, 2, 3].into(), inner: InnerTestA { hidden: Some(false) }, oid: None }, recursion: RecursiveChoice::Leaf },
350        "Deep-Sequence",
351        "<nested><wine><true /></wine><grappa>00010203</grappa><inner><hidden><false /></hidden></inner></nested><recursion><Leaf /></recursion>"
352    );
353    round_trip!(
354        extended_sequence,
355        NestedTestA,
356        NestedTestA {
357            wine: true,
358            grappa: vec![0, 1, 2, 3].into(),
359            inner: InnerTestA {
360                hidden: Some(false),
361            },
362            oid: Some(ObjectIdentifier::from(Oid::const_new(&[1, 8270, 4, 1]))),
363        },
364        "NestedTestA",
365        "<wine><true /></wine><grappa>00010203</grappa><inner><hidden><false /></hidden></inner><oid>1.8270.4.1</oid>"
366    );
367    round_trip!(
368        sequence_with_defaults,
369        DefaultSequence,
370        DefaultSequence { bool_with_default: false, recursion: vec![DefaultSequence { bool_with_default: true, recursion: vec![] }] },
371        "DefaultSequence",
372        "<recursion><DefaultSequence><bool-df><true /></bool-df><recursion /></DefaultSequence></recursion>"
373    );
374    round_trip!(
375        extended_sequence_with_inner_none,
376        NestedTestA,
377        NestedTestA {
378            wine: true,
379            grappa: vec![0, 1, 2, 3].into(),
380            inner: InnerTestA { hidden: None },
381            oid: Some(ObjectIdentifier::from(Oid::const_new(&[1, 8270, 4, 1])))
382        },
383        "NestedTestA",
384        "<wine><true /></wine><grappa>00010203</grappa><inner /><oid>1.8270.4.1</oid>"
385    );
386    round_trip!(
387        extensible_sequence_without_extensions,
388        NestedTestA,
389        NestedTestA {
390            wine: true,
391            grappa: vec![0, 1, 2, 3].into(),
392            inner: InnerTestA { hidden: None },
393            oid: None
394        },
395        "NestedTestA",
396        "<wine><true /></wine><grappa>00010203</grappa><inner />"
397    );
398    round_trip!(
399        sequence_of_nulls,
400        SequenceOfNulls,
401        vec![(), (), ()],
402        "SEQUENCE_OF",
403        "<NULL /><NULL /><NULL />"
404    );
405    round_trip!(
406        sequence_of_choices,
407        SequenceOfChoices,
408        vec![
409            ChoiceType::EnumVariant(EnumType::First),
410            ChoiceType::EnumVariant(EnumType::Second)
411        ],
412        "SEQUENCE_OF",
413        "<enum><eins /></enum><enum><zwei /></enum>"
414    );
415    round_trip!(
416        sequence_of_delegate_choices,
417        SequenceOfDelegateChoices,
418        vec![
419            ChoiceDelegate(ChoiceType::EnumVariant(EnumType::First)),
420            ChoiceDelegate(ChoiceType::EnumVariant(EnumType::Second))
421        ],
422        "SEQUENCE_OF",
423        "<enum><eins /></enum><enum><zwei /></enum>"
424    );
425    round_trip!(
426        sequence_of_enums,
427        SequenceOfEnums,
428        vec![EnumType::First, EnumType::Second],
429        "SEQUENCE_OF",
430        "<eins /><zwei />"
431    );
432    round_trip!(
433        sequence_of_bitstrings,
434        SequenceOfBitStrings,
435        vec![bitvec![u8, Msb0; 1,0,1,1,0,0,1]],
436        "SEQUENCE_OF",
437        "<BIT_STRING>1011001</BIT_STRING>"
438    );
439    round_trip!(
440        sequence_of_integers,
441        SequenceOfIntegers,
442        vec![-1, 2, 3],
443        "SEQUENCE_OF",
444        "<INTEGER>-1</INTEGER><INTEGER>2</INTEGER><INTEGER>3</INTEGER>"
445    );
446    round_trip!(
447        sequence_of_sequence_of_sequences,
448        SequenceOfSequenceOfSequences,
449        vec![vec![InnerTestA { hidden: Some(true) }, InnerTestA { hidden: Some(false) }], vec![InnerTestA { hidden: None }], vec![]],
450        "SEQUENCE_OF",
451        "<SEQUENCE_OF><InnerTestA><hidden><true /></hidden></InnerTestA><InnerTestA><hidden><false /></hidden></InnerTestA></SEQUENCE_OF><SEQUENCE_OF><InnerTestA /></SEQUENCE_OF><SEQUENCE_OF />"
452    );
453    round_trip!(
454        sequence_of_enum_sequences,
455        SequenceOfEnumSequences,
456        vec![
457            EnumSequence {
458                enum_field: EnumType::First
459            },
460            EnumSequence {
461                enum_field: EnumType::Second
462            }
463        ],
464        "SEQUENCE_OF",
465        "<Enum-Sequence><enum-field><eins /></enum-field></Enum-Sequence><Enum-Sequence><enum-field><zwei /></enum-field></Enum-Sequence>"
466    );
467    round_trip!(
468        set_of_bools,
469        SetOfBools,
470        SetOf::from_vec(vec![true]),
471        "SET_OF",
472        "<true />"
473    );
474    round_trip!(
475        set_of_enums,
476        SetOfEnums,
477        SetOf::from_vec(vec![EnumType::Second]),
478        "SET_OF",
479        "<zwei />"
480    );
481    round_trip!(
482        set_of_integers,
483        SetOfIntegers,
484        SetOf::from_vec(vec![-1]),
485        "SET_OF",
486        "<INTEGER>-1</INTEGER>"
487    );
488    round_trip!(
489        set_of_sequence_of_sequences,
490        SetOfSequenceOfSequences,
491        SetOf::from_vec(vec![vec![InnerTestA { hidden: None }]]),
492        "SET_OF",
493        "<SEQUENCE_OF><InnerTestA /></SEQUENCE_OF>"
494    );
495    round_trip!(
496        set_of_enum_sequences,
497        SetOfEnumSequences,
498        SetOf::from_vec(vec![EnumSequence {
499            enum_field: EnumType::Second
500        }]),
501        "SET_OF",
502        "<Enum-Sequence><enum-field><zwei /></enum-field></Enum-Sequence>"
503    );
504    round_trip!(
505        sequence_with_element_after_choice,
506        SequenceWithChoice,
507        SequenceWithChoice {
508            recursion: RecursiveChoice::Leaf,
509            nested: NestedTestA {
510                wine: true,
511                grappa: vec![0, 1, 2, 3].into(),
512                inner: InnerTestA {
513                    hidden: Some(false),
514                },
515                oid: Some(ObjectIdentifier::from(Oid::const_new(&[1, 8270, 4, 1]))),
516            }
517        },
518        "SequenceWithChoice",
519        "<recursion><Leaf /></recursion><nested><wine><true /></wine><grappa>00010203</grappa><inner><hidden><false /></hidden></inner><oid>1.8270.4.1</oid></nested>"
520    );
521    round_trip!(
522        sequence_with_element_after_sequence_of,
523        SequenceWithSequenceOf,
524        SequenceWithSequenceOf {
525            ids: vec![42, 13],
526            flag: false,
527            int: Integer::from(12),
528            enum_val: EnumType::First
529        },
530        "SequenceWithSequenceOf",
531        "<ids><INTEGER>42</INTEGER><INTEGER>13</INTEGER></ids><flag><false /></flag><int>12</int><enum_val><eins /></enum_val>"
532    );
533    round_trip!(
534        sequence_with_element_after_set_of,
535        SequenceWithSetOf,
536        SequenceWithSetOf {
537            ids: SetOf::from_vec(vec![42, 13]),
538            flag: false,
539            int: Integer::from(12),
540            enum_val: EnumType::First
541        },
542        "SequenceWithSetOf",
543        "<ids><INTEGER>42</INTEGER><INTEGER>13</INTEGER></ids><flag><false /></flag><int>12</int><enum_val><eins /></enum_val>"
544    );
545
546    #[test]
547    fn set_of_round_trip() {
548        let first = EnumSequence {
549            enum_field: EnumType::First,
550        };
551        let second = EnumSequence {
552            enum_field: EnumType::Second,
553        };
554        let value = SetOf::<EnumSequence>::from_vec(vec![first.clone(), second.clone()]);
555        let encoded = crate::xer::encode(&value).unwrap();
556        let decoded: SetOf<EnumSequence> = crate::xer::decode(&encoded).unwrap();
557
558        assert!(String::from_utf8(encoded.clone())
559            .unwrap()
560            .contains("<Enum-Sequence><enum-field><zwei /></enum-field></Enum-Sequence>"));
561        assert!(String::from_utf8(encoded)
562            .unwrap()
563            .contains("<Enum-Sequence><enum-field><eins /></enum-field></Enum-Sequence>"));
564        assert!(decoded.contains(&first));
565        assert!(decoded.contains(&second));
566    }
567}