1pub use super::oer::*;
4use crate::error::{DecodeError, EncodeError};
5use crate::types::Constraints;
6
7pub fn decode<T: crate::Decode>(input: &[u8]) -> Result<T, DecodeError> {
12 T::decode(&mut Decoder::new(
13 crate::types::BitStr::from_slice(input),
14 de::DecoderOptions::coer(),
15 ))
16}
17pub fn encode<T: crate::Encode>(value: &T) -> Result<alloc::vec::Vec<u8>, EncodeError> {
23 let mut enc = Encoder::new(enc::EncoderOptions::coer());
24 value.encode(&mut enc)?;
25 Ok(enc.output())
26}
27pub fn decode_with_constraints<T: crate::Decode>(
32 constraints: Constraints,
33 input: &[u8],
34) -> Result<T, DecodeError> {
35 T::decode_with_constraints(
36 &mut Decoder::new(
37 crate::types::BitStr::from_slice(input),
38 de::DecoderOptions::coer(),
39 ),
40 constraints,
41 )
42}
43pub fn encode_with_constraints<T: crate::Encode>(
48 constraints: Constraints,
49 value: &T,
50) -> Result<alloc::vec::Vec<u8>, EncodeError> {
51 let mut enc = Encoder::new(enc::EncoderOptions::coer());
52 value.encode_with_constraints(&mut enc, constraints)?;
53 Ok(enc.output())
54}
55
56#[cfg(test)]
57#[allow(clippy::items_after_statements)]
58mod tests {
59 use crate as rasn;
60 use crate::prelude::*;
61 use crate::types::constraints::{Bounded, Size, Value};
62 use bitvec::prelude::*;
63 #[test]
64 fn bool() {
65 round_trip!(coer, bool, true, &[0xff]);
66 round_trip!(coer, bool, false, &[0]);
67 }
68 #[test]
69 #[allow(clippy::too_many_lines)]
70 fn integer_no_constraints() {
71 round_trip!(coer, Integer, 0.into(), &[0x01u8, 0x00]);
74 round_trip!(coer, Integer, 1.into(), &[0x01u8, 0x01]);
75 round_trip!(coer, Integer, (-1).into(), &[0x01u8, 0xff]);
76 round_trip!(coer, Integer, 255.into(), &[0x02u8, 0x00, 0xff]);
77 round_trip!(coer, Integer, (-255).into(), &[0x02u8, 0xff, 0x01]);
78 round_trip!(coer, Integer, i16::MAX.into(), &[0x02u8, 0x7f, 0xff]);
79 round_trip!(coer, Integer, i16::MIN.into(), &[0x02u8, 0x80, 0x00]);
80 round_trip!(
81 coer,
82 Integer,
83 (i32::from(i16::MAX) + 1).into(),
84 &[0x03u8, 0x00u8, 0x80, 0x00]
85 );
86 round_trip!(
87 coer,
88 Integer,
89 (i32::from(i16::MIN) - 1).into(),
90 &[0x03u8, 0xff, 0x7f, 0xff]
91 );
92 round_trip!(
93 coer,
94 Integer,
95 i32::MAX.into(),
96 &[0x04u8, 0x7f, 0xff, 0xff, 0xff]
97 );
98 round_trip!(
99 coer,
100 Integer,
101 i32::MIN.into(),
102 &[0x04u8, 0x80, 0x00, 0x00, 0x00]
103 );
104 round_trip!(
105 coer,
106 Integer,
107 (i64::from(i32::MAX) + 1).into(),
108 &[0x05u8, 0x00, 0x80, 0x00, 0x00, 0x00]
109 );
110 round_trip!(
111 coer,
112 Integer,
113 (i64::from(i32::MIN) - 1).into(),
114 &[0x05u8, 0xff, 0x7f, 0xff, 0xff, 0xff]
115 );
116 round_trip!(
117 coer,
118 Integer,
119 i64::MAX.into(),
120 &[0x08u8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
121 );
122 round_trip!(
123 coer,
124 Integer,
125 i64::MIN.into(),
126 &[0x08u8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
127 );
128 round_trip!(
129 coer,
130 Integer,
131 (i128::from(i64::MAX) + 1).into(),
132 &[0x09u8, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
133 );
134 round_trip!(
135 coer,
136 Integer,
137 (i128::from(i64::MIN) - 1).into(),
138 &[0x09u8, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
139 );
140 round_trip!(
141 coer,
142 Integer,
143 i128::MAX.into(),
144 &[
145 0x10u8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
146 0xff, 0xff, 0xff, 0xff
147 ]
148 );
149 round_trip!(
150 coer,
151 Integer,
152 i128::MIN.into(),
153 &[
154 0x10u8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00
156 ]
157 );
158 round_trip!(
159 coer,
160 Integer,
161 Integer::from(i128::MAX) + 1,
162 &[
163 0x11u8, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 0x00, 0x00, 0x00, 0x00, 0x00
165 ]
166 );
167 round_trip!(
168 coer,
169 Integer,
170 Integer::from(i128::MIN) - 1,
171 &[
172 0x11u8, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
173 0xff, 0xff, 0xff, 0xff, 0xff
174 ]
175 );
176 }
177 #[test]
178 fn test_integer_with_unsigned_constraints() {
179 type A = ConstrainedInteger<0, { u8::MAX as i128 }>;
180 type B = ConstrainedInteger<0, { u16::MAX as i128 }>;
181 type C = ConstrainedInteger<0, { u32::MAX as i128 }>;
182 type D = ConstrainedInteger<0, { u64::MAX as i128 }>;
183 type E = ConstrainedInteger<0, { i128::MAX }>;
184 type F = ConstrainedInteger<2, { u16::MAX as i128 }>;
185
186 round_trip!(coer, A, 0.into(), &[0x00]);
187 round_trip!(coer, A, 5.into(), &[0x05]);
188 round_trip!(coer, A, 255.into(), &[0xff]);
189 round_trip!(coer, B, 0.into(), &[0x00, 0x00]);
191 round_trip!(coer, B, 255.into(), &[0x00, 0xff]);
192 round_trip!(coer, C, 0.into(), &[0x00, 0x00, 0x00, 0x00]);
193 round_trip!(coer, C, u16::MAX.into(), &[0x00, 0x00, 0xff, 0xff]);
194 round_trip!(
195 coer,
196 D,
197 0.into(),
198 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
199 );
200 round_trip!(
201 coer,
202 D,
203 u32::MAX.into(),
204 &[0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]
205 );
206 round_trip!(
208 coer,
209 E,
210 (i128::from(u64::MAX) + 1).into(),
211 &[0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
212 );
213 round_trip!(coer, F, 2.into(), &[0x00, 0x02]);
214 encode_error!(coer, A, (-1).into());
216 encode_error!(coer, B, (-1).into());
217 encode_error!(coer, C, (-1).into());
218 encode_error!(coer, D, (-1).into());
219 encode_error!(coer, E, (-1).into());
220 encode_error!(coer, F, (1).into());
221 encode_error!(coer, A, (u16::from(u8::MAX) + 1).into());
222 encode_error!(coer, B, (u32::from(u16::MAX) + 1).into());
223 encode_error!(coer, C, (u64::from(u32::MAX) + 1).into());
224 encode_error!(coer, D, (u128::from(u64::MAX) + 1).into());
225 }
226 #[test]
227 fn test_integer_with_signed_constraints() {
228 type A = ConstrainedInteger<{ i8::MIN as i128 }, { i8::MAX as i128 }>;
229 type B = ConstrainedInteger<{ i16::MIN as i128 }, { i16::MAX as i128 }>;
230 type C = ConstrainedInteger<{ i32::MIN as i128 }, { i32::MAX as i128 }>;
231 type D = ConstrainedInteger<{ i64::MIN as i128 }, { i64::MAX as i128 }>;
232 type E = ConstrainedInteger<-5, 5>;
233
234 round_trip!(coer, A, 0.into(), &[0x00]);
235 round_trip!(coer, A, (-1).into(), &[0xff]);
236 round_trip!(coer, A, i8::MIN.into(), &[0x80]);
237 round_trip!(coer, A, i8::MAX.into(), &[0x7f]);
238 round_trip!(coer, B, 0.into(), &[0x00, 0x00]);
240 round_trip!(coer, B, (-1).into(), &[0xff, 0xff]);
241 round_trip!(coer, B, i8::MIN.into(), &[0xff, 0x80]);
242 round_trip!(coer, B, i8::MAX.into(), &[0x00, 0x7f]);
243 round_trip!(coer, B, i16::MIN.into(), &[0x80, 0x00]);
244 round_trip!(coer, B, i16::MAX.into(), &[0x7f, 0xff]);
245
246 round_trip!(coer, C, 0.into(), &[0x00, 0x00, 0x00, 0x00]);
247 round_trip!(coer, C, (-1).into(), &[0xff, 0xff, 0xff, 0xff]);
248 round_trip!(coer, C, i16::MIN.into(), &[0xff, 0xff, 0x80, 0x00]);
249 round_trip!(coer, C, i16::MAX.into(), &[0x00, 0x00, 0x7f, 0xff]);
250 round_trip!(coer, C, i32::MIN.into(), &[0x80, 0x00, 0x00, 0x00]);
251 round_trip!(coer, C, i32::MAX.into(), &[0x7f, 0xff, 0xff, 0xff]);
252
253 round_trip!(
254 coer,
255 D,
256 0.into(),
257 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
258 );
259 round_trip!(
260 coer,
261 D,
262 (-1).into(),
263 &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
264 );
265 round_trip!(
266 coer,
267 D,
268 i32::MIN.into(),
269 &[0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00]
270 );
271 round_trip!(
272 coer,
273 D,
274 i32::MAX.into(),
275 &[0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff]
276 );
277 round_trip!(
278 coer,
279 D,
280 i64::MIN.into(),
281 &[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
282 );
283 round_trip!(
284 coer,
285 D,
286 i64::MAX.into(),
287 &[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
288 );
289 round_trip!(coer, E, 4.into(), &[0x04]);
290 round_trip!(coer, E, (-4).into(), &[0xfc]);
291
292 encode_error!(coer, A, (i16::from(i8::MIN) - 1).into());
294 encode_error!(coer, B, (i32::from(i16::MIN) - 1).into());
295 encode_error!(coer, C, (i64::from(i32::MIN) - 1).into());
296 encode_error!(coer, D, (i128::from(i64::MIN) - 1).into());
297
298 encode_error!(coer, A, (i16::from(i8::MAX) + 1).into());
299 encode_error!(coer, B, (i32::from(i16::MAX) + 1).into());
300 encode_error!(coer, C, (i64::from(i32::MAX) + 1).into());
301 encode_error!(coer, D, (i128::from(i64::MAX) + 1).into());
302 }
303 #[test]
304 fn test_integer_single_constraint() {
305 round_trip_with_constraints!(
306 coer,
307 Integer,
308 Constraints::new(&[Constraint::Value(Value::new(Bounded::Single(5)).into())]),
309 5.into(),
310 &[0x05]
311 );
312 }
313 #[test]
314 fn test_enumerated() {
315 #[derive(AsnType, Clone, Copy, Debug, Decode, Encode, PartialEq)]
316 #[rasn(enumerated, crate_root = "crate")]
317 enum Enum1 {
318 Green,
319 Red,
320 Blue,
321 }
322 round_trip!(coer, Enum1, Enum1::Green, &[0x00]);
323 round_trip!(coer, Enum1, Enum1::Red, &[0x01]);
324 round_trip!(coer, Enum1, Enum1::Blue, &[0x02]);
325 #[derive(AsnType, Clone, Copy, Debug, Decode, Encode, PartialEq)]
327 #[rasn(enumerated, crate_root = "crate")]
328 #[allow(clippy::items_after_statements)]
329 enum Enum2 {
330 Red,
331 Blue,
332 Green,
333 #[rasn(extension_addition_group)]
334 Yellow,
335 Purple,
336 }
337 round_trip!(coer, Enum2, Enum2::Red, &[0x00]);
338 round_trip!(coer, Enum2, Enum2::Yellow, &[0x03]);
339 round_trip!(coer, Enum2, Enum2::Purple, &[0x04]);
340 #[derive(AsnType, Clone, Copy, Debug, Decode, Encode, PartialEq)]
341 #[rasn(enumerated, crate_root = "crate")]
342 #[allow(clippy::items_after_statements)]
343 enum Enum3 {
344 Red = 5,
345 Blue = 6,
346 Green = 7,
347 }
348 round_trip!(coer, Enum3, Enum3::Red, &[0x05]);
349 round_trip!(coer, Enum3, Enum3::Blue, &[0x06]);
350 round_trip!(coer, Enum3, Enum3::Green, &[0x07]);
351
352 #[derive(AsnType, Clone, Copy, Debug, Decode, Encode, PartialEq)]
353 #[rasn(enumerated, crate_root = "crate")]
354 #[allow(clippy::items_after_statements)]
355 enum Enum4 {
356 Yes = 1000,
357 No = -1000,
358 }
359 round_trip!(coer, Enum4, Enum4::Yes, &[0x82, 0x03, 0xe8]);
360 round_trip!(coer, Enum4, Enum4::No, &[0x82, 0xfc, 0x18]);
361 }
362 #[test]
363 fn test_bit_string() {
364 round_trip!(
365 coer,
366 BitString,
367 BitString::from_slice(&[0x01]),
368 &[0x02, 0x00, 0x01]
369 );
370 round_trip!(coer, BitString, BitString::from_slice(&[]), &[0x01, 0x00]);
371 let mut bv = bitvec![u8, Msb0;];
372 bv.extend_from_raw_slice(&[0xff]);
373 bv.push(false);
374 bv.push(true);
375 bv.extend([false; 4].iter());
376 round_trip_with_constraints!(
378 coer,
379 BitString,
380 Constraints::new(&[Constraint::Size(Size::new(Bounded::Single(14)).into())]),
381 BitString::from_bitslice(&bv),
382 &[0b1111_1111, 0b0100_0000]
383 );
384 round_trip!(
385 coer,
386 BitString,
387 BitString::from_bitslice(&bv),
388 &[0x03u8, 0x02, 0b1111_1111, 0b0100_0000]
389 );
390 encode_error_with_constraints!(
391 coer,
392 BitString,
393 Constraints::new(&[Constraint::Size(Size::new(Bounded::Single(15)).into())]),
394 BitString::from_bitslice(&bv)
395 );
396 }
397 #[test]
398 fn test_octet_string() {
399 round_trip!(
400 coer,
401 OctetString,
402 OctetString::from_static(&[0x01]),
403 &[0x01, 0x01]
404 );
405 round_trip_with_constraints!(
406 coer,
407 OctetString,
408 Constraints::new(&[Constraint::Size(Size::new(Bounded::Single(5)).into())]),
409 OctetString::from_static(&[0x01u8, 0x02, 0x03, 0x04, 0x05]),
410 &[0x01u8, 0x02, 0x03, 0x04, 0x05]
411 );
412 round_trip_with_constraints!(
413 coer,
414 OctetString,
415 Constraints::new(&[Constraint::Size(
416 Size::new(Bounded::Range {
417 start: Some(3),
418 end: Some(6)
419 })
420 .into()
421 )]),
422 OctetString::from_static(&[0x01u8, 0x02, 0x03, 0x04, 0x05]),
423 &[0x05u8, 0x01, 0x02, 0x03, 0x04, 0x05]
424 );
425 encode_error_with_constraints!(
426 coer,
427 OctetString,
428 Constraints::new(&[Constraint::Size(Size::new(Bounded::Single(5)).into())]),
429 OctetString::from_static(&[0x01u8, 0x02, 0x03, 0x04])
430 );
431 encode_error_with_constraints!(
432 coer,
433 OctetString,
434 Constraints::new(&[Constraint::Size(
435 Size::new(Bounded::Range {
436 start: Some(3),
437 end: Some(6)
438 })
439 .into()
440 )]),
441 OctetString::from_static(&[0x01u8, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07])
442 );
443 encode_error_with_constraints!(
444 coer,
445 OctetString,
446 Constraints::new(&[Constraint::Size(
447 Size::new(Bounded::Range {
448 start: Some(3),
449 end: Some(6)
450 })
451 .into()
452 )]),
453 OctetString::from_static(&[0x01u8, 0x02])
454 );
455 }
456 #[test]
457 fn test_object_identifier() {
458 round_trip!(
461 coer,
462 ObjectIdentifier,
463 ObjectIdentifier::new(vec![1u32, 2]).unwrap(),
464 &[0x01u8, 0x2a]
465 );
466 round_trip!(
467 coer,
468 ObjectIdentifier,
469 ObjectIdentifier::new(vec![1, 2, 3321]).unwrap(),
470 &[0x03u8, 0x2a, 0x99, 0x79]
471 );
472 }
473 #[test]
474 fn test_choice() {
475 #[derive(AsnType, Decode, Debug, Encode, PartialEq)]
477 #[rasn(crate_root = "crate")]
478 #[rasn(choice, automatic_tags)]
479 #[non_exhaustive]
480 enum Choice {
481 Normal(Integer),
482 High(Integer),
483 #[rasn(extension_addition)]
484 Medium(Integer),
485 }
486 round_trip!(
487 coer,
488 Choice,
489 Choice::Normal(333.into()),
490 &[0x80, 0x02, 0x01, 0x4d]
491 );
492 round_trip!(
493 coer,
494 Choice,
495 Choice::High(333.into()),
496 &[0x81, 0x02, 0x01, 0x4d]
497 );
498 round_trip!(
499 coer,
500 Choice,
501 Choice::Medium(333.into()),
502 &[0x82, 0x03, 0x02, 0x01, 0x4d]
503 );
504
505 #[derive(AsnType, Decode, Debug, Encode, PartialEq)]
506 #[rasn(crate_root = "crate")]
507 #[rasn(choice, automatic_tags)]
508 #[non_exhaustive]
509 enum BoolChoice {
510 A(bool),
511 #[rasn(extension_addition)]
512 B(bool),
513 C(Choice),
514 }
515 round_trip!(coer, BoolChoice, BoolChoice::A(true), &[0x80, 0xff]);
516 round_trip!(coer, BoolChoice, BoolChoice::B(true), &[0x81, 0x01, 0xff]);
517 round_trip!(
518 coer,
519 BoolChoice,
520 BoolChoice::C(Choice::Normal(333.into())),
521 &[0x82, 0x80, 0x02, 0x01, 0x4d]
522 );
523 #[derive(AsnType, Decode, Debug, Encode, PartialEq)]
524 #[rasn(choice, automatic_tags)]
525 #[non_exhaustive]
526 enum TripleChoice {
527 A(bool),
528 B(BoolChoice),
529 }
530 round_trip!(coer, TripleChoice, TripleChoice::A(true), &[0x80, 0xff]);
531 round_trip!(
532 coer,
533 TripleChoice,
534 TripleChoice::B(BoolChoice::C(Choice::Normal(333.into()))),
535 &[0x81, 0x82, 0x80, 0x02, 0x01, 0x4d]
536 );
537 #[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq)]
538 #[rasn(crate_root = "crate")]
539 #[rasn(choice, automatic_tags)]
540 #[non_exhaustive]
541 enum TestChoice {
542 Number1(()),
543 Number2(bool),
544 Number3(Box<TopLevel>),
545 }
546
547 #[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq)]
548 #[rasn(crate_root = "crate")]
549 #[rasn(automatic_tags)]
550 struct TopLevel {
551 #[rasn(value("1..=8"))]
552 pub test: u8,
553 pub choice: TestChoice,
554 }
555
556 impl TopLevel {
557 pub fn new(test: u8, choice: TestChoice) -> Self {
558 Self { test, choice }
559 }
560 }
561
562 let test_value = TopLevel::new(
563 1,
564 TestChoice::Number3(Box::new(TopLevel {
565 test: 2,
566 choice: TestChoice::Number1(()),
567 })),
568 );
569 round_trip!(coer, TopLevel, test_value, &[1, 130, 2, 128]);
570 }
571 #[test]
572 fn test_numeric_string() {
573 round_trip!(
574 coer,
575 NumericString,
576 "123".try_into().unwrap(),
577 &[0x03, 0x31, 0x32, 0x33]
578 );
579 round_trip_with_constraints!(
580 coer,
581 NumericString,
582 Constraints::new(&[Constraint::Size(Size::new(Bounded::Single(3)).into())]),
583 "123".try_into().unwrap(),
584 &[0x31, 0x32, 0x33]
585 );
586 round_trip_with_constraints!(
587 coer,
588 NumericString,
589 Constraints::new(&[Constraint::Size(
590 Size::new(Bounded::Range {
591 start: Some(3),
592 end: Some(7)
593 })
594 .into()
595 )]),
596 "123".try_into().unwrap(),
597 &[0x03, 0x31, 0x32, 0x33]
598 );
599 }
600 #[test]
601 fn test_printable_string() {
602 round_trip!(
603 coer,
604 PrintableString,
605 "foo".try_into().unwrap(),
606 &[0x03, 0x66, 0x6f, 0x6f]
607 );
608 round_trip!(
609 coer,
610 PrintableString,
611 " '()+,-./:=?".try_into().unwrap(),
612 &[0x0c, 0x20, 0x27, 0x28, 0x29, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x3a, 0x3d, 0x3f]
613 );
614 round_trip_with_constraints!(
615 coer,
616 PrintableString,
617 Constraints::new(&[Constraint::Size(Size::new(Bounded::Single(3)).into())]),
618 "foo".try_into().unwrap(),
619 &[0x66, 0x6f, 0x6f]
620 );
621 round_trip_with_constraints!(
622 coer,
623 PrintableString,
624 Constraints::new(&[Constraint::Size(
625 Size::new(Bounded::Range {
626 start: Some(3),
627 end: Some(7)
628 })
629 .into()
630 )]),
631 "foo".try_into().unwrap(),
632 &[0x03, 0x66, 0x6f, 0x6f]
633 );
634 }
635 #[test]
636 fn test_visible_string() {
637 round_trip!(
638 coer,
639 VisibleString,
640 "foo".try_into().unwrap(),
641 &[0x03, 0x66, 0x6f, 0x6f]
642 );
643 round_trip_with_constraints!(
644 coer,
645 VisibleString,
646 Constraints::new(&[Constraint::Size(Size::new(Bounded::Single(3)).into())]),
647 "foo".try_into().unwrap(),
648 &[0x66, 0x6f, 0x6f]
649 );
650 round_trip_with_constraints!(
651 coer,
652 VisibleString,
653 Constraints::new(&[Constraint::Size(
654 Size::new(Bounded::Range {
655 start: Some(3),
656 end: Some(7)
657 })
658 .into()
659 )]),
660 "foo".try_into().unwrap(),
661 &[0x03, 0x66, 0x6f, 0x6f]
662 );
663 }
664 #[test]
665 fn test_ia5_string() {
666 round_trip!(
667 coer,
668 Ia5String,
669 "foo".try_into().unwrap(),
670 &[0x03, 0x66, 0x6f, 0x6f]
671 );
672 round_trip_with_constraints!(
673 coer,
674 Ia5String,
675 Constraints::new(&[Constraint::Size(Size::new(Bounded::Single(3)).into())]),
676 "foo".try_into().unwrap(),
677 &[0x66, 0x6f, 0x6f]
678 );
679 round_trip_with_constraints!(
680 coer,
681 Ia5String,
682 Constraints::new(&[Constraint::Size(
683 Size::new(Bounded::Range {
684 start: Some(3),
685 end: Some(7)
686 })
687 .into()
688 )]),
689 "foo".try_into().unwrap(),
690 &[0x03, 0x66, 0x6f, 0x6f]
691 );
692 }
693 #[test]
694 fn test_general_string() {
695 round_trip!(
696 coer,
697 GeneralString,
698 GeneralString::from_bytes("".as_bytes()).unwrap(),
699 &[0x00]
700 );
701 round_trip!(
702 coer,
703 GeneralString,
704 GeneralString::from_bytes("2".as_bytes()).unwrap(),
705 &[0x01, 0x32]
706 );
707 }
708 #[test]
709 fn test_utf8_string() {
710 round_trip!(coer, Utf8String, "".into(), &[0x00]);
711 round_trip!(coer, Utf8String, "2".into(), &[0x01, 0x32]);
712 round_trip!(
713 coer,
714 Utf8String,
715 "2".repeat(128),
716 &[0x81, 0x80]
717 .iter()
718 .chain("2".repeat(128).as_bytes().iter())
719 .copied()
720 .collect::<Vec<_>>()
721 );
722 round_trip!(
723 coer,
724 Utf8String,
725 "ÄÖÄÖÄÖÄÖ12e4Ä".into(),
726 &[
727 0x16, 0xc3, 0x84, 0xc3, 0x96, 0xc3, 0x84, 0xc3, 0x96, 0xc3, 0x84, 0xc3, 0x96, 0xc3,
728 0x84, 0xc3, 0x96, 0x31, 0x32, 0x65, 0x34, 0xc3, 0x84
729 ]
730 );
731 round_trip_with_constraints!(
732 coer,
733 Utf8String,
734 Constraints::new(&[Constraint::Size(Size::new(Bounded::Single(3)).into())]),
735 "foo".into(),
736 &[0x66, 0x6f, 0x6f]
737 );
738 }
739 #[test]
740 fn test_teletext_string() {
741 round_trip!(
742 coer,
743 TeletexString,
744 TeletexString::from("123".as_bytes().to_vec()),
745 &[0x03, 0x31, 0x32, 0x33]
746 );
747 }
748 #[test]
749 fn test_generalized_time() {
750 use chrono::NaiveDate;
751 let offset = chrono::FixedOffset::east_opt(0).unwrap();
752 let dt = NaiveDate::from_ymd_opt(2080, 10, 9)
753 .unwrap()
754 .and_hms_micro_opt(13, 0, 5, 342_000)
755 .unwrap()
756 .and_local_timezone(offset);
757 round_trip!(
758 coer,
759 GeneralizedTime,
760 GeneralizedTime::from(dt.unwrap(),),
761 &[
762 0x13, 0x32, 0x30, 0x38, 0x30, 0x31, 0x30, 0x30, 0x39, 0x31, 0x33, 0x30, 0x30, 0x30,
763 0x35, 0x2e, 0x33, 0x34, 0x32, 0x5a
764 ]
765 );
766
767 let data = [
768 24, 19, 43, 53, 49, 54, 49, 53, 32, 32, 48, 53, 50, 52, 48, 57, 52, 48, 50, 48, 90,
769 ];
770
771 assert!(crate::der::decode::<crate::types::Open>(&data).is_err());
772 }
773 #[test]
774 fn test_utc_time() {
775 round_trip!(
778 coer,
779 UtcTime,
780 UtcTime::from(
781 chrono::NaiveDate::from_ymd_opt(2019, 10, 9)
782 .unwrap()
783 .and_hms_opt(13, 0, 5)
784 .unwrap()
785 .and_utc()
786 ),
787 &[0x0d, 0x31, 0x39, 0x31, 0x30, 0x30, 0x39, 0x31, 0x33, 0x30, 0x30, 0x30, 0x35, 0x5a]
788 );
789 }
790 #[test]
791 fn test_sequence_no_extensions() {
794 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
795 #[rasn(crate_root = "crate")]
797 struct Sequence1 {
798 a: Integer,
799 b: Integer,
800 }
801 round_trip!(
802 coer,
803 Sequence1,
804 Sequence1 {
805 a: 1.into(),
806 b: 2.into()
807 },
808 &[0x01, 0x01, 0x01, 0x02]
809 );
810
811 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
812 #[rasn(automatic_tags)]
813 struct Sequence2 {
814 a: bool,
815 }
816 round_trip!(coer, Sequence2, Sequence2 { a: true }, &[0xff]);
817
818 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
819 #[rasn(automatic_tags)]
820 struct Sequence3 {
821 a: bool,
822 b: Sequence1,
823 }
824 round_trip!(
825 coer,
826 Sequence3,
827 Sequence3 {
828 a: true,
829 b: Sequence1 {
830 a: 1.into(),
831 b: 2.into()
832 }
833 },
834 &[0xff, 0x01, 0x01, 0x01, 0x02]
835 );
836 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
837 #[rasn(crate_root = "crate", choice, automatic_tags)]
838 enum Choice1 {
839 A(bool),
840 B(Sequence1),
841 }
842 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
843 #[rasn(crate_root = "crate")]
844 struct Sequence4 {
845 a: Integer,
846 b: Choice1,
847 }
848 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
849 #[rasn(crate_root = "crate")]
850 struct Sequence5 {
851 a: bool,
852 b: Sequence4,
853 }
854 round_trip!(
855 coer,
856 Sequence5,
857 Sequence5 {
858 a: true,
859 b: Sequence4 {
860 a: 1.into(),
861 b: Choice1::B(Sequence1 {
862 a: 1.into(),
863 b: 2.into()
864 })
865 }
866 },
867 &[0xff, 0x01, 0x01, 0x81, 0x01, 0x01, 0x01, 0x02]
868 );
869 }
870 #[test]
871 fn test_sequence_default_option() {
872 fn default_a() -> Integer {
873 0.into()
874 }
875 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
876 #[rasn(automatic_tags)]
877 struct Sequence1 {
878 #[rasn(default = "default_a")]
879 a: Integer,
880 }
881 round_trip!(coer, Sequence1, Sequence1 { a: 0.into() }, &[0x00]);
882 round_trip!(
883 coer,
884 Sequence1,
885 Sequence1 { a: 1.into() },
886 &[0b1000_0000, 0x01, 0x01]
887 );
888 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
889 #[rasn(automatic_tags)]
890 struct Sequence2 {
891 a: Integer,
892 b: Option<Integer>,
893 }
894 round_trip!(
895 coer,
896 Sequence2,
897 Sequence2 {
898 a: 1.into(),
899 b: Some(2.into())
900 },
901 &[0b1000_0000, 0x01, 0x01, 0x01, 0x02]
902 );
903 round_trip!(
904 coer,
905 Sequence2,
906 Sequence2 {
907 a: 1.into(),
908 b: None
909 },
910 &[0x00, 0x01, 0x01]
911 );
912 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
913 #[rasn(automatic_tags)]
914 struct Sequence4 {
915 #[rasn(default = "default_a")]
916 a: Integer, b: Option<Integer>,
918 }
919 round_trip!(
920 coer,
921 Sequence4,
922 Sequence4 {
923 a: 0.into(),
924 b: None
925 },
926 &[0x00]
927 );
928 round_trip!(
929 coer,
930 Sequence4,
931 Sequence4 {
932 a: 1.into(),
933 b: Some(3.into())
934 },
935 &[0b1100_0000, 0x01, 0x01, 0x01, 0x03]
936 );
937 }
938 #[test]
939 fn test_sequence_with_extensions() {
940 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
941 #[rasn(automatic_tags)]
942 #[non_exhaustive]
943 struct Sequence1 {
944 a: bool,
945 }
946 round_trip!(coer, Sequence1, Sequence1 { a: true }, &[0x00, 0xff]);
947 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
948 #[rasn(automatic_tags)]
949 #[non_exhaustive]
950 struct Sequence2 {
951 a: bool,
952 #[rasn(extension_addition)]
953 b: Option<bool>,
954 #[rasn(extension_addition)]
955 c: Option<bool>,
956 }
957 round_trip!(
958 coer,
959 Sequence2,
960 Sequence2 {
961 a: true,
962 b: Some(true),
963 c: Some(true)
964 },
965 &[0x80, 0xff, 0x02, 0x06, 0xc0, 0x01, 0xff, 0x01, 0xff]
966 );
967 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
968 #[rasn(automatic_tags)]
969 #[non_exhaustive]
970 struct Sequence3 {
971 a: bool,
972 #[rasn(extension_addition_group)]
973 b: Option<Sequence4>,
974 }
975 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
976 #[rasn(automatic_tags)]
977 struct Sequence4 {
978 a: bool,
979 }
980 round_trip!(
981 coer,
982 Sequence3,
983 Sequence3 { a: true, b: None },
984 &[0x00, 0xff]
985 );
986 round_trip!(
987 coer,
988 Sequence3,
989 Sequence3 {
990 a: true,
991 b: Some(Sequence4 { a: true })
992 },
993 &[0x80, 0xff, 0x02, 0x07, 0x80, 0x01, 0xff]
994 );
995 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
996 #[rasn(automatic_tags)]
997 #[non_exhaustive]
998 struct Sequence5 {
999 a: bool,
1000 #[rasn(extension_addition)]
1001 b: Option<bool>,
1002 }
1003 round_trip!(
1004 coer,
1005 Sequence5,
1006 Sequence5 { a: true, b: None },
1007 &[0x00, 0xff]
1008 );
1009 round_trip!(
1010 coer,
1011 Sequence5,
1012 Sequence5 {
1013 a: true,
1014 b: Some(true)
1015 },
1016 &[0x80, 0xff, 0x02, 0x07, 0x80, 0x01, 0xff]
1017 );
1018 }
1019 #[test]
1020 fn test_sequence_of() {
1021 round_trip!(
1022 coer,
1023 SequenceOf::<Integer>,
1024 SequenceOf::<Integer>::from(vec![]),
1025 &[0x01, 0x00]
1026 );
1027 round_trip!(
1028 coer,
1029 SequenceOf::<Integer>,
1030 SequenceOf::<Integer>::from(vec![1.into(), 2.into()]),
1031 &[0x01, 0x02, 0x01, 0x01, 0x01, 0x02]
1032 );
1033 }
1034 #[test]
1035 fn test_set() {
1036 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
1037 #[rasn(set, tag(application, 0))]
1038 struct Foo {
1039 #[rasn(tag(explicit(444)))]
1040 a: Integer,
1041 #[rasn(tag(explicit(5)))]
1042 b: Integer,
1043 #[rasn(tag(application, 9))]
1044 c: Integer,
1045 }
1046 round_trip!(
1047 coer,
1048 Foo,
1049 Foo {
1050 a: 5.into(),
1051 b: 6.into(),
1052 c: 7.into(),
1053 },
1054 &[0x01, 0x07, 0x01, 0x06, 0x01, 0x05]
1055 );
1056 }
1057 #[test]
1058 fn test_sequence_with_nested_opt() {
1059 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
1060 #[rasn(automatic_tags)]
1061 struct Sequence1 {
1062 a: Integer,
1063 b: Option<Integer>,
1064 }
1065 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
1066 #[rasn(automatic_tags)]
1067 struct Sequence2 {
1068 a: Integer,
1069 b: Option<Sequence1>,
1070 }
1071 round_trip!(
1072 coer,
1073 Sequence2,
1074 Sequence2 {
1075 a: 1.into(),
1076 b: Some(Sequence1 {
1077 a: 2.into(),
1078 b: Some(3.into())
1079 })
1080 },
1081 &[0x80, 0x01, 0x01, 0x80, 0x01, 0x02, 0x01, 0x03]
1082 );
1083 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
1084 #[rasn(automatic_tags)]
1085 struct Sequence3 {
1086 a: Integer,
1087 b: Sequence2,
1088 }
1089 round_trip!(
1090 coer,
1091 Sequence3,
1092 Sequence3 {
1093 a: 1.into(),
1094 b: Sequence2 {
1095 a: 2.into(),
1096 b: Some(Sequence1 {
1097 a: 3.into(),
1098 b: Some(4.into())
1099 })
1100 }
1101 },
1102 &[0x01, 0x01, 0x80, 0x01, 0x02, 0x80, 0x01, 0x03, 0x01, 0x04]
1103 );
1104 }
1105 #[test]
1106 fn test_boxed_sequence() {
1107 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
1108 #[rasn(automatic_tags)]
1109 struct Sequence1 {
1110 a: Integer,
1111 b: Option<Integer>,
1112 }
1113 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
1114 #[rasn(automatic_tags)]
1115 struct Sequence2 {
1116 a: Integer,
1117 b: Box<Sequence1>,
1118 }
1119 round_trip!(
1120 coer,
1121 Sequence2,
1122 Sequence2 {
1123 a: 1.into(),
1124 b: Box::new(Sequence1 {
1125 a: 2.into(),
1126 b: Some(3.into())
1127 })
1128 },
1129 &[0x01, 0x01, 0x80, 0x01, 0x02, 0x01, 0x03]
1130 );
1131 }
1132 #[test]
1133 fn test_nested_boxed_sequence() {
1134 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
1135 #[rasn(choice, automatic_tags)]
1136 enum Choice1 {
1137 A(bool),
1138 B(Box<Sequence1>),
1139 }
1140 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
1141 #[rasn(automatic_tags)]
1142 struct Sequence1 {
1143 a: Option<Integer>,
1144 b: Choice1,
1145 }
1146 round_trip!(
1147 coer,
1148 Sequence1,
1149 Sequence1 {
1150 a: Some(1.into()),
1151 b: Choice1::B(Box::new(Sequence1 {
1152 a: Some(2.into()),
1153 b: Choice1::A(true)
1154 }))
1155 },
1156 &[0x80, 0x01, 0x01, 0x81, 0x80, 0x01, 0x02, 0x80, 0xff]
1157 );
1158 }
1159 #[test]
1160 fn test_empty_sequence() {
1161 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
1162 #[rasn(automatic_tags)]
1163 struct Sequence1 {}
1164 round_trip!(coer, Sequence1, Sequence1 {}, &[]);
1165
1166 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
1168 #[rasn(automatic_tags)]
1169 struct Sequence2 {
1170 a: Option<Integer>,
1171 b: Option<Integer>,
1172 }
1173 round_trip!(coer, Sequence2, Sequence2 { a: None, b: None }, &[0x00]);
1174 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
1176 #[rasn(automatic_tags)]
1177 struct Sequence3 {
1178 #[rasn(default = "default_a")]
1179 a: Integer,
1180 #[rasn(default = "default_b")]
1181 b: Integer,
1182 }
1183 fn default_a() -> Integer {
1184 0.into()
1185 }
1186 fn default_b() -> Integer {
1187 1.into()
1188 }
1189 round_trip!(
1190 coer,
1191 Sequence3,
1192 Sequence3 {
1193 a: 0.into(),
1194 b: 1.into()
1195 },
1196 &[0x00]
1197 );
1198 }
1199}