1pub 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
15pub fn decode<T: crate::Decode>(input: &[u8]) -> Result<T, crate::error::DecodeError> {
19 T::decode(&mut de::Decoder::new(input)?)
20}
21
22pub 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}