1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(test), no_std)]
3#![warn(missing_docs)]
4
5extern crate alloc;
6
7#[macro_use]
8pub mod macros;
9
10mod bits;
11mod codec;
12pub mod de;
13pub mod enc;
14pub mod error;
15mod num;
16mod per;
17pub mod types;
18
19pub mod aper;
22pub mod ber;
23pub mod cer;
24pub mod coer;
25pub mod der;
26pub mod jer;
27pub mod oer;
28pub mod uper;
29pub mod xer;
30
31#[doc(inline)]
32pub use self::{
33 codec::Codec,
34 de::{Decode, Decoder},
35 enc::{Encode, Encoder},
36 types::AsnType,
37};
38
39#[doc(inline)]
40#[cfg(feature = "compiler")]
41#[cfg_attr(docsrs, doc(cfg(feature = "compiler")))]
42pub use rasn_compiler as compiler;
44
45pub mod prelude {
48 pub use crate::{
49 de::{Decode, Decoder},
50 enc::{Encode, Encoder},
51 macros,
52 types::*,
53 };
54}
55
56#[cfg(test)]
57mod tests {
58 use super::prelude::*;
59
60 #[track_caller]
61 fn round_trip<T: Decode + Encode + PartialEq + core::fmt::Debug>(value: &T) {
62 macro_rules! codecs {
63 ($($codec:ident),+ $(,)?) => {
64 $(
65 pretty_assertions::assert_eq!(
66 value,
67 &match crate::$codec::decode::<T>(
68 &match crate::$codec::encode(value).map_err(|error| error.to_string()) {
69 Ok(value) => value,
70 Err(error) => panic!("error encoding: {}", error),
71 }
72 ) {
73 Ok(value) => value,
74 Err(error) => panic!("error decoding: {}", error),
75 }
76 );
77 )+
78 }
79 }
80
81 codecs!(uper, aper, oer, coer, ber);
82 }
83
84 #[test]
85 fn null() {
86 round_trip(&());
87 }
88
89 #[test]
90 fn bool() {
91 round_trip(&true);
92 round_trip(&false);
93 }
94
95 macro_rules! integer_tests {
96 ($($integer:ident),*) => {
97 $(
98 #[test]
99 fn $integer() {
100 let min = <$integer>::MIN;
101 let max = <$integer>::MAX;
102 let half_max = <$integer>::MAX / 2;
103 let half_min = <$integer>::MIN / 2;
104
105 round_trip(&min);
106 round_trip(&half_min);
107 round_trip(&half_max);
108 round_trip(&max);
109 }
110 )*
111 }
112 }
113
114 integer_tests! {
115 i8,
116 i16,
117 i32,
118 i64,
119 isize,
121 u8,
122 u16,
123 u32,
124 u64,
125 usize
128 }
129
130 #[test]
131 fn integer() {
132 round_trip(&89);
133 round_trip(&256);
134 round_trip(&u64::MAX);
135 round_trip(&i64::MIN);
136 }
137
138 #[test]
139 fn semi_constrained_integer() {
140 #[derive(PartialEq, Debug)]
141 struct CustomInt(i32);
142
143 impl crate::AsnType for CustomInt {
144 const TAG: Tag = Tag::INTEGER;
145 const CONSTRAINTS: Constraints =
146 macros::constraints!(macros::value_constraint!(start: 127));
147 }
148
149 impl crate::Encode for CustomInt {
150 fn encode_with_tag_and_constraints<'b, E: crate::Encoder<'b>>(
151 &self,
152 encoder: &mut E,
153 tag: Tag,
154 constraints: Constraints,
155 _: Identifier,
156 ) -> Result<(), E::Error> {
157 encoder
158 .encode_integer::<i128>(tag, constraints, &self.0.into(), Identifier::EMPTY)
159 .map(drop)
160 }
161 }
162
163 impl crate::Decode for CustomInt {
164 fn decode_with_tag_and_constraints<D: crate::Decoder>(
165 decoder: &mut D,
166 tag: Tag,
167 constraints: Constraints,
168 ) -> Result<Self, D::Error> {
169 Ok(Self(decoder.decode_integer::<i32>(tag, constraints)?))
170 }
171 }
172
173 round_trip(&CustomInt(256));
174 round_trip(&CustomInt(i32::MAX));
175 }
176
177 #[test]
178 fn bit_string() {
179 round_trip(&BitString::from_slice(&[1u8, 2, 3, 4, 5]));
180 round_trip(&BitString::from_slice(&[5u8, 4, 3, 2, 1]));
181 }
182
183 #[test]
184 fn octet_string() {
185 round_trip(&OctetString::from(vec![1u8, 2, 3, 4, 5]));
186 round_trip(&OctetString::from(vec![5u8, 4, 3, 2, 1]));
187 }
188
189 #[test]
190 fn utf8_string() {
191 round_trip(&crate::types::Utf8String::from("Jones"));
192 }
193
194 #[test]
195 fn visible_string() {
196 round_trip(&crate::types::Utf8String::from("Jones"));
197 }
198
199 #[test]
200 fn long_sequence_of() {
201 round_trip(&vec![5u8; 0xffff]);
202 }
203
204 #[test]
205 fn object_identifier() {
206 round_trip(&ObjectIdentifier::new(vec![1, 2]).unwrap());
207 round_trip(&ObjectIdentifier::new(vec![1, 2, 840]).unwrap());
208 round_trip(&ObjectIdentifier::new(vec![1, 2, 840, 113549]).unwrap());
209 round_trip(&ObjectIdentifier::new(vec![1, 2, 840, 113549, 1]).unwrap());
210 round_trip(&ObjectIdentifier::new(vec![0, 3, 0, 3]).unwrap());
211 }
212
213 #[test]
214 fn enumerated() {
215 #[derive(AsnType, Clone, Copy, Debug, Decode, Encode, PartialEq)]
216 #[rasn(enumerated, crate_root = "crate")]
217 enum Day {
218 Mon,
219 Tues,
220 Weds,
221 Thurs,
222 Fri,
223 Sat,
224 Sun,
225 }
226
227 round_trip(&Day::Mon);
228 round_trip(&Day::Tues);
229 round_trip(&Day::Sat);
230 }
231 #[test]
233 fn decode_with_iterator() {
234 use crate::types::Integer;
235
236 macro_rules! test_codec_iter {
237 ($codec:ident, $codec_enum:expr) => {
238 let mut data = vec![];
239 let integer_before1 = Integer::from(i64::from(i32::MIN) - 1);
240 let integer_before2 = Integer::from(i64::from(i32::MAX) - 1);
241 let integer_before3 = Integer::from(i64::from(i32::MIN) - i64::from(i16::MIN));
242 data.extend(crate::$codec::encode(&integer_before1).unwrap());
243 data.extend(crate::$codec::encode(&integer_before2).unwrap());
244 let mut iter = crate::de::iter(&data, $codec_enum);
245 let decoded: Integer = iter.next().unwrap().unwrap();
246 assert_eq!(integer_before1, decoded);
247 let int3_bytes = crate::$codec::encode(&integer_before3).unwrap();
248 iter.append_bytes(&int3_bytes);
249 let decoded: Integer = iter.next().unwrap().unwrap();
250 assert_eq!(integer_before2, decoded);
251 let decoded: Integer = iter.next().unwrap().unwrap();
252 assert_eq!(integer_before3, decoded);
253 };
254 }
255
256 test_codec_iter!(oer, crate::Codec::Oer);
257 test_codec_iter!(coer, crate::Codec::Coer);
258 test_codec_iter!(uper, crate::Codec::Uper);
259 test_codec_iter!(aper, crate::Codec::Aper);
260 test_codec_iter!(ber, crate::Codec::Ber);
261 test_codec_iter!(cer, crate::Codec::Cer);
262 test_codec_iter!(der, crate::Codec::Der);
263 }
264}