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