1use crate::types::Constraints;
7
8pub use super::per::*;
9
10pub fn decode<T: crate::Decode>(input: &[u8]) -> Result<T, crate::error::DecodeError> {
12 crate::per::decode(de::DecoderOptions::aligned(), input)
13}
14pub fn decode_with_remainder<T: crate::Decode>(
19 input: &[u8],
20) -> Result<(T, &[u8]), crate::error::DecodeError> {
21 crate::per::decode_with_remainder(de::DecoderOptions::aligned(), input)
22}
23
24pub fn encode<T: crate::Encode>(
26 value: &T,
27) -> Result<alloc::vec::Vec<u8>, crate::error::EncodeError> {
28 crate::per::encode(enc::EncoderOptions::aligned(), value)
29}
30
31pub fn decode_with_constraints<T: crate::Decode>(
33 constraints: Constraints,
34 input: &[u8],
35) -> Result<T, crate::error::DecodeError> {
36 crate::per::decode_with_constraints(de::DecoderOptions::aligned(), constraints, input)
37}
38
39pub fn encode_with_constraints<T: crate::Encode>(
41 constraints: Constraints,
42 value: &T,
43) -> Result<alloc::vec::Vec<u8>, crate::error::EncodeError> {
44 crate::per::encode_with_constraints(enc::EncoderOptions::aligned(), constraints, value)
45}
46
47#[cfg(test)]
48mod tests {
49 use crate::{
50 macros::*,
51 prelude::*,
52 types::{constraints::*, *},
53 };
54
55 #[test]
56 fn bitstring() {
57 use bitvec::prelude::*;
58 #[allow(dead_code)]
62 #[derive(Debug, AsnType, Decode, Encode, PartialEq)]
63 #[rasn(crate_root = "crate")]
64 struct D {
65 a: bool,
66 b: BitString,
67 }
68
69 #[allow(dead_code)]
70 #[derive(Debug, AsnType, Decode, Encode, PartialEq)]
71 #[rasn(crate_root = "crate")]
72 struct E {
73 a: bool,
74 #[rasn(size(1))]
75 b: BitString,
76 #[rasn(size(16))]
77 c: BitString,
78 }
79
80 #[allow(dead_code)]
81 #[derive(Debug, AsnType, Decode, Encode, PartialEq)]
82 #[rasn(crate_root = "crate")]
83 struct G {
84 a: BitString,
85 b: bool,
86 }
87
88 #[allow(dead_code)]
95 #[derive(Debug, AsnType, Decode, Encode, PartialEq)]
96 #[rasn(crate_root = "crate")]
97 struct M {
98 a: bool,
99 #[rasn(size("1..=160", extensible))]
100 b: BitString,
101 }
102
103 round_trip!(
107 aper,
108 BitString,
109 bitvec::bitvec![u8, Msb0; 0, 1, 0, 0],
110 &[0x04, 0x40]
111 );
112 round_trip!(
128 aper,
129 BitString,
130 BitString::from_vec([0x55; 2048].into()),
131 &*{
132 let mut bytes = vec![0xc1];
133 bytes.extend([0x55; 2048]);
134 bytes.push(0x00);
135 bytes
136 }
137 );
138 }
156
157 #[test]
158 #[allow(clippy::too_many_lines)]
159 fn integer() {
160 type B = ConstrainedInteger<5, 99>;
161
162 #[derive(Debug, AsnType, Decode, Encode, PartialEq)]
163 #[rasn(crate_root = "crate")]
164 struct C {
165 a: bool,
166 b: Integer,
167 c: bool,
168 #[rasn(value("-10..=400"))]
169 d: Integer,
170 }
171
172 type D = ConstrainedInteger<0, 254>;
173 type E = ConstrainedInteger<0, 255>;
174 type F = ConstrainedInteger<0, 256>;
175 type G = ConstrainedInteger<0, 65535>;
176 type H = ConstrainedInteger<0, 65536>;
177 type I = ConstrainedInteger<0, 10_000_000_000>;
178
179 #[derive(Debug, AsnType, Decode, Encode, PartialEq)]
180 #[rasn(crate_root = "crate")]
181 struct J {
182 a: bool,
183 #[rasn(value("0..=254"))]
184 b: Integer,
185 #[rasn(value("0..=255"))]
186 c: Integer,
187 d: bool,
188 #[rasn(value("0..=256"))]
189 e: Integer,
190 }
191
192 #[derive(Debug, AsnType, Decode, Encode, PartialEq)]
193 #[rasn(crate_root = "crate")]
194 struct L {
195 #[rasn(value("7..=7"))]
196 a: Integer,
197 }
198
199 type N = ConstrainedInteger<0, 65535>;
200 type O = ConstrainedInteger<0, 65536>;
201 type P = ConstrainedInteger<0, 2_147_483_647>;
202 type Q = ConstrainedInteger<0, 4_294_967_295>;
203 type R = ConstrainedInteger<0, 4_294_967_296>;
204
205 #[derive(Debug, AsnType, Decode, Encode, PartialEq)]
206 #[rasn(crate_root = "crate")]
207 struct S {
208 a: bool,
209 #[rasn(value("-10000..=704000000000000001"))]
210 b: Integer,
211 c: bool,
212 }
213
214 round_trip!(aper, Integer, 32768.into(), &[0x03, 0x00, 0x80, 0x00]);
215 round_trip!(aper, Integer, 32767.into(), &[0x02, 0x7f, 0xff]);
216 round_trip!(aper, Integer, 256.into(), &[0x02, 0x01, 0x00]);
217 round_trip!(aper, Integer, 255.into(), &[0x02, 0x00, 0xff]);
218 round_trip!(aper, Integer, 128.into(), &[0x02, 0x00, 0x80]);
219 round_trip!(aper, Integer, 127.into(), &[0x01, 0x7f]);
220 round_trip!(aper, Integer, 1.into(), &[0x01, 0x01]);
221 round_trip!(aper, Integer, 0.into(), &[0x01, 0x00]);
222 round_trip!(aper, Integer, (-1).into(), &[0x01, 0xff]);
223 round_trip!(aper, Integer, (-128).into(), &[0x01, 0x80]);
224 round_trip!(aper, Integer, (-129).into(), &[0x02, 0xff, 0x7f]);
225 round_trip!(aper, Integer, (-256).into(), &[0x02, 0xff, 0x00]);
226 round_trip!(aper, Integer, (-32768).into(), &[0x02, 0x80, 0x00]);
227 round_trip!(aper, Integer, (-32769).into(), &[0x03, 0xff, 0x7f, 0xff]);
228 round_trip!(aper, B, B::new(5), &[0x00]);
229 round_trip!(aper, B, B::new(6), &[0x02]);
230 round_trip!(aper, B, B::new(99), &[0xbc]);
231 round_trip!(
232 aper,
233 C,
234 C {
235 a: true,
236 b: Integer::from(43_554_344_223_i64),
237 c: false,
238 d: Integer::from(-9)
239 },
240 &[0x80, 0x05, 0x0a, 0x24, 0x0a, 0x8d, 0x1f, 0x00, 0x00, 0x01]
241 );
242 round_trip!(aper, D, D::new(253), &[0xfd]);
243 round_trip!(aper, E, E::new(253), &[0xfd]);
244 round_trip!(aper, F, F::new(253), &[0x00, 0xfd]);
245 round_trip!(aper, G, G::new(253), &[0x00, 0xfd]);
246 round_trip!(aper, H, H::new(253), &[0x00, 0xfd]);
247 round_trip!(aper, H, H::new(256), &[0x40, 0x01, 0x00]);
248 round_trip!(aper, H, H::new(65536), &[0x80, 0x01, 0x00, 0x00]);
249 round_trip!(aper, I, I::new(0), &[0x00, 0x00]);
250 round_trip!(aper, I, I::new(1), &[0x00, 0x01]);
251 round_trip!(
252 aper,
253 I,
254 I::new(10_000_000_000_i64),
255 &[0x80, 0x02, 0x54, 0x0b, 0xe4, 0x00]
256 );
257 round_trip!(
258 aper,
259 J,
260 J {
261 a: false,
262 b: Integer::from(253),
263 c: Integer::from(253),
264 d: false,
265 e: Integer::from(253)
266 },
267 &[0x7e, 0x80, 0xfd, 0x00, 0x00, 0xfd]
268 );
269 round_trip!(
270 aper,
271 L,
272 L {
273 a: Integer::from(7)
274 },
275 &[]
276 );
277 round_trip!(aper, N, N::new(1), &[0x00, 0x01]);
279 round_trip!(aper, N, N::new(255), &[0x00, 0xff]);
280 round_trip!(aper, N, N::new(256), &[0x01, 0x00]);
281 round_trip!(aper, N, N::new(65535), &[0xff, 0xff]);
282 round_trip!(aper, O, O::new(1), &[0x00, 0x01]);
283 round_trip!(aper, O, O::new(255), &[0x00, 0xff]);
284 round_trip!(aper, O, O::new(256), &[0x40, 0x01, 0x00]);
285 round_trip!(aper, O, O::new(65535), &[0x40, 0xff, 0xff]);
286 round_trip!(aper, O, O::new(65536), &[0x80, 0x01, 0x00, 0x00]);
287 round_trip!(aper, P, P::new(1), &[0x00, 0x01]);
288 round_trip!(aper, P, P::new(255), &[0x00, 0xff]);
289 round_trip!(aper, P, P::new(256), &[0x40, 0x01, 0x00]);
290 round_trip!(aper, P, P::new(65535), &[0x40, 0xff, 0xff]);
291 round_trip!(aper, P, P::new(65536), &[0x80, 0x01, 0x00, 0x00]);
292 round_trip!(aper, P, P::new(16_777_215), &[0x80, 0xff, 0xff, 0xff]);
293 round_trip!(aper, P, P::new(16_777_216), &[0xc0, 0x01, 0x00, 0x00, 0x00]);
294 round_trip!(
295 aper,
296 P,
297 P::new(100_000_000),
298 &[0xc0, 0x05, 0xf5, 0xe1, 0x00]
299 );
300 round_trip!(
301 aper,
302 Q,
303 Q::new(4_294_967_295_u64),
304 &[0xc0, 0xff, 0xff, 0xff, 0xff]
305 );
306 round_trip!(
307 aper,
308 R,
309 R::new(4_294_967_296_u64),
310 &[0x80, 0x01, 0x00, 0x00, 0x00, 0x00]
311 );
312 round_trip!(
313 aper,
314 S,
315 S {
316 a: true,
317 b: 0.into(),
318 c: true
319 },
320 &[0x90, 0x27, 0x10, 0x80]
321 );
322 }
323
324 #[test]
325 fn visible_string() {
326 #[allow(dead_code)]
339 #[derive(Debug, AsnType, Decode, Encode, PartialEq)]
340 #[rasn(crate_root = "crate")]
341 struct D {
342 a: bool,
343 #[rasn(size(1))]
344 b: VisibleString,
345 }
346
347 #[allow(dead_code)]
348 #[derive(Debug, AsnType, Decode, Encode, PartialEq)]
349 #[rasn(crate_root = "crate")]
350 struct E {
351 a: bool,
352 #[rasn(size(2))]
353 b: VisibleString,
354 }
355
356 #[allow(dead_code)]
357 #[derive(Debug, AsnType, Decode, Encode, PartialEq)]
358 #[rasn(crate_root = "crate")]
359 struct F {
360 a: bool,
361 #[rasn(size(3))]
362 b: VisibleString,
363 }
364
365 #[allow(dead_code)]
366 #[derive(Debug, AsnType, Decode, Encode, PartialEq)]
367 #[rasn(crate_root = "crate")]
368 struct G {
369 a: bool,
370 #[rasn(size("0..=1"))]
371 b: VisibleString,
372 }
373
374 #[allow(dead_code)]
375 #[derive(Debug, AsnType, Decode, Encode, PartialEq)]
376 #[rasn(crate_root = "crate")]
377 struct H {
378 a: bool,
379 #[rasn(size("0..=2"))]
380 b: VisibleString,
381 }
382 const PERMITTED_CONSTRAINT: Constraints = constraints!(
425 permitted_alphabet_constraint!(&[
426 b'a' as u32,
427 b'b' as u32,
428 b'c' as u32,
429 b'd' as u32,
430 b'e' as u32,
431 b'f' as u32,
432 b'g' as u32,
433 b'h' as u32,
434 b'i' as u32,
435 b'j' as u32,
436 b'k' as u32,
437 b'l' as u32,
438 b'm' as u32,
439 b'n' as u32,
440 b'o' as u32,
441 b'p' as u32,
442 b'q' as u32,
443 b'r' as u32,
444 b's' as u32,
445 b't' as u32,
446 b'u' as u32,
447 b'v' as u32,
448 b'w' as u32,
449 b'x' as u32,
450 b'y' as u32,
451 b'z' as u32,
452 ]),
453 size_constraint!(1, 255)
454 );
455 round_trip_with_constraints!(
456 aper,
457 VisibleString,
458 PERMITTED_CONSTRAINT,
459 VisibleString::try_from("hej").unwrap(),
460 &[0x02, 0x68, 0x65, 0x6a]
461 );
462 const PERMITTED_CONSTRAINT_2: Constraints =
463 constraints!(permitted_alphabet_constraint!(&[b'a' as u32]));
464 round_trip_with_constraints!(
465 aper,
466 VisibleString,
467 PERMITTED_CONSTRAINT_2,
468 VisibleString::try_from("a").unwrap(),
469 &[0x01]
470 );
471 }
472
473 #[test]
474 fn issue_192() {
475 use crate as rasn;
477
478 use rasn::AsnType;
479
480 #[derive(rasn::AsnType, rasn::Encode, rasn::Decode, Debug, Clone, PartialEq, Eq)]
481 #[rasn(automatic_tags)]
482 #[non_exhaustive]
483 pub struct Updates {
484 pub updates: Vec<u8>,
485 }
486
487 #[derive(rasn::AsnType, rasn::Encode, rasn::Decode, Debug, Clone, PartialEq, Eq)]
488 #[rasn(automatic_tags)]
489 #[rasn(choice)]
490 #[non_exhaustive]
491 pub enum Message {
492 Updates(Updates),
493 }
494
495 let msg = Message::Updates(Updates { updates: vec![1] });
496
497 round_trip!(aper, Message, msg, &[0, 1, 1]);
498 }
499
500 #[test]
501 fn issue_201() {
502 use crate as rasn;
503 use crate::prelude::*;
504
505 const T124_IDENTIFIER_KEY: &Oid = Oid::const_new(&[0, 0, 20, 124, 0, 1]);
506 #[derive(Debug, AsnType, Encode, rasn::Decode)]
507 #[rasn(choice, automatic_tags)]
508 enum Key {
509 #[rasn(tag(explicit(5)))]
510 Object(ObjectIdentifier),
511 H221NonStandard(OctetString),
512 }
513
514 #[derive(Debug, AsnType, rasn::Encode, rasn::Decode)]
515 #[rasn(automatic_tags)]
516 struct ConnectData {
517 t124_identifier_key: Key,
518 connect_pdu: OctetString,
519 }
520
521 let connect_pdu: OctetString = vec![0u8, 1u8, 2u8, 3u8].into();
522 let connect_data = ConnectData {
523 t124_identifier_key: Key::Object(T124_IDENTIFIER_KEY.into()),
524 connect_pdu,
525 };
526
527 let encoded = rasn::aper::encode(&connect_data).expect("failed to encode");
528 assert_eq!(
529 encoded,
530 vec![0x00, 0x05, 0x00, 0x14, 0x7C, 0x00, 0x01, 0x04, 0x00, 0x01, 0x02, 0x03]
531 );
532 let _: ConnectData = rasn::aper::decode(&encoded).expect("failed to decode");
533 }
534}