1pub mod de;
4pub mod enc;
5mod identifier;
6mod rules;
7
8pub use identifier::Identifier;
9pub(crate) use rules::EncodingRules;
10
11pub fn decode<T: crate::Decode>(input: &[u8]) -> Result<T, crate::error::DecodeError> {
15 T::decode(&mut de::Decoder::new(input, de::DecoderOptions::ber()))
16}
17
18pub fn encode<T: crate::Encode>(
22 value: &T,
23) -> Result<alloc::vec::Vec<u8>, crate::error::EncodeError> {
24 let mut enc = enc::Encoder::new(enc::EncoderOptions::ber());
25
26 value.encode(&mut enc)?;
27
28 Ok(enc.output())
29}
30
31pub fn encode_scope(
35 encode_fn: impl FnOnce(&mut crate::ber::enc::Encoder) -> Result<(), crate::error::EncodeError>,
36) -> Result<alloc::vec::Vec<u8>, crate::error::EncodeError> {
37 let mut enc = crate::ber::enc::Encoder::new(crate::ber::enc::EncoderOptions::ber());
38
39 (encode_fn)(&mut enc)?;
40
41 Ok(enc.output())
42}
43
44#[cfg(test)]
45mod tests {
46 use alloc::borrow::ToOwned;
47 use alloc::vec;
48 use alloc::vec::Vec;
49 use chrono::{DateTime, FixedOffset, NaiveDate, Utc};
50 use de::DecodeErrorKind;
51
52 use crate::types::*;
53
54 use super::*;
55
56 #[derive(Clone, Copy, Hash, Debug, PartialEq)]
57 struct C0;
58 impl AsnType for C0 {
59 const TAG: Tag = Tag::new(Class::Context, 0);
60 }
61
62 #[test]
63 fn oversized_integer() {
64 const DATA: &[u8] = &[0x02, 0x06, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66];
65
66 assert!(matches!(
67 &*decode::<u32>(DATA).unwrap_err().kind,
68 DecodeErrorKind::IntegerOverflow { max_width: 32 }
69 ));
70
71 assert!(matches!(
72 &*decode::<i32>(DATA).unwrap_err().kind,
73 DecodeErrorKind::IntegerOverflow { max_width: 32 }
74 ));
75 }
76
77 #[test]
78 fn leading_integer_bytes() {
79 const DATA: &[u8] = &[0x02, 0x06, 0x00, 0x00, 0x33, 0x44, 0x55, 0x66];
80 assert_eq!(decode::<u32>(DATA).unwrap(), 0x33445566u32);
81
82 const SIGNED_DATA: &[u8] = &[0x02, 0x06, 0xFF, 0xFF, 0x83, 0x44, 0x55, 0x66];
83 assert_eq!(decode::<i32>(SIGNED_DATA).unwrap(), -2092673690);
84 }
85
86 #[test]
87 fn bit_string() {
88 const DATA: &[u8] = &[0, 0xD0];
89 let small = BitString::from_vec(DATA.to_owned());
90 let bits = BitString::from_vec([0x0A, 0x3B, 0x5F, 0x29, 0x1C, 0xD0][..].to_owned());
91 let padding_test = BitString::from_element(0x42);
92 let padding_expected: &[u8] = &[0x03, 0x02, 0x00, 0x42];
93 let trailing_test = bitvec::bitvec![u8, bitvec::prelude::Msb0; 1, 0, 0, 0, 0, 1, 1, 0];
94 let trailing_expected: &[u8] = &[0x03, 0x02, 0x00, 0x86];
95
96 assert_eq!(
97 small,
98 decode::<BitString>(&encode(&small).unwrap()).unwrap()
99 );
100 assert_eq!(bits, decode::<BitString>(&encode(&bits).unwrap()).unwrap());
101 assert_eq!(padding_expected, encode(&padding_test).unwrap());
102 assert_eq!(trailing_expected, encode(&trailing_test).unwrap());
103 }
104
105 #[test]
106 fn implicit_prefix() {
107 type MyInteger = Implicit<C0, u64>;
108
109 let new_int = MyInteger::new(5);
110
111 assert_eq!(new_int, decode(&encode(&new_int).unwrap()).unwrap());
112 }
113
114 #[test]
115 fn explicit_prefix() {
116 type MyInteger = Explicit<C0, u64>;
117
118 let new_int = MyInteger::new(5);
119 let data = &[0xA0, 3, 0x2, 0x1, 5][..];
120
121 assert_eq!(data, &encode(&new_int).unwrap());
122 assert_eq!(new_int, decode(&encode(&new_int).unwrap()).unwrap());
123 }
124
125 #[test]
126 fn implicit_tagged_constructed() {
127 type ImpVec = Implicit<C0, Vec<i32>>;
128
129 let value = ImpVec::new(vec![1, 2]);
130 let data = &[0xA0, 6, 2, 1, 1, 2, 1, 2][..];
131
132 assert_eq!(data, &*crate::ber::encode(&value).unwrap());
133 assert_eq!(value, crate::ber::decode::<ImpVec>(data).unwrap());
134 }
135
136 #[test]
137 fn explicit_empty_tag() {
138 type EmptyTag = Explicit<C0, Option<()>>;
139
140 let value = EmptyTag::new(None);
141 let data = &[0xA0, 0][..];
142
143 assert_eq!(data, &*crate::ber::encode(&value).unwrap());
144 assert_eq!(value, crate::ber::decode::<EmptyTag>(data).unwrap());
145 }
146
147 #[test]
148 #[allow(clippy::items_after_statements)]
149 fn set() {
150 #[derive(Debug, PartialEq)]
151 struct Set {
152 age: u32,
153 name: Utf8String,
154 }
155
156 impl AsnType for Set {
157 const TAG: Tag = Tag::SET;
158 }
159
160 impl crate::types::Constructed for Set {
161 const FIELDS: crate::types::fields::Fields =
162 crate::types::fields::Fields::from_static(&[
163 crate::types::fields::Field::new_required(u32::TAG, u32::TAG_TREE, "age"),
164 crate::types::fields::Field::new_required(
165 Utf8String::TAG,
166 Utf8String::TAG_TREE,
167 "name",
168 ),
169 ]);
170 }
171
172 let example = Set {
173 age: 1,
174 name: "Jane".into(),
175 };
176 let age_then_name = [0x31, 0x9, 0x2, 0x1, 0x1, 0xC, 0x4, 0x4a, 0x61, 0x6e, 0x65];
177 let name_then_age = [0x31, 0x9, 0xC, 0x4, 0x4a, 0x61, 0x6e, 0x65, 0x2, 0x1, 0x1];
178
179 assert_eq!(&age_then_name[..], crate::ber::encode(&example).unwrap());
180
181 assert_eq!(
182 crate::ber::decode::<Set>(&age_then_name).unwrap(),
183 crate::ber::decode::<Set>(&name_then_age).unwrap()
184 );
185
186 impl crate::Decode for Set {
187 fn decode_with_tag_and_constraints<D: crate::Decoder>(
188 decoder: &mut D,
189 tag: Tag,
190 _: Constraints,
191 ) -> Result<Self, D::Error> {
192 use crate::de::Error;
193
194 #[derive(crate::AsnType, crate::Decode)]
195 #[rasn(crate_root = "crate")]
196 #[rasn(choice)]
197 pub enum Fields {
198 Age(u32),
199 Name(Utf8String),
200 }
201 let codec = decoder.codec();
202 decoder.decode_set::<Fields, _, _, _>(
203 tag,
204 |decoder, indice, tag| match (indice, tag) {
205 (0, u32::TAG) => <_>::decode(decoder).map(Fields::Age),
206 (1, Utf8String::TAG) => <_>::decode(decoder).map(Fields::Name),
207 (_, _) => Err(D::Error::custom("unknown field", codec)),
208 },
209 |fields| {
210 let mut age = None;
211 let mut name = None;
212
213 for field in fields {
214 match field {
215 Fields::Age(value) => age = value.into(),
216 Fields::Name(value) => name = value.into(),
217 }
218 }
219
220 Ok(Self {
221 age: age.ok_or_else(|| D::Error::missing_field("age", codec))?,
222 name: name.ok_or_else(|| D::Error::missing_field("name", codec))?,
223 })
224 },
225 )
226 }
227 }
228
229 impl crate::Encode for Set {
230 fn encode_with_tag_and_constraints<EN: crate::Encoder>(
231 &self,
232 encoder: &mut EN,
233 tag: crate::Tag,
234 _: Constraints,
235 ) -> Result<(), EN::Error> {
236 encoder.encode_set::<Self, _>(tag, |encoder| {
237 self.age.encode(encoder)?;
238 self.name.encode(encoder)?;
239 Ok(())
240 })?;
241
242 Ok(())
243 }
244 }
245 }
246 #[test]
247 fn test_generalized_time() {
248 let offset = chrono::FixedOffset::east_opt(0).unwrap();
250 let dt = NaiveDate::from_ymd_opt(2080, 10, 9)
251 .unwrap()
252 .and_hms_micro_opt(13, 0, 5, 342_000)
253 .unwrap()
254 .and_local_timezone(offset);
255 round_trip!(
256 ber,
257 GeneralizedTime,
258 GeneralizedTime::from(dt.unwrap(),),
259 &[
260 0x18, 0x13, 0x32, 0x30, 0x38, 0x30, 0x31, 0x30, 0x30, 0x39, 0x31, 0x33, 0x30, 0x30,
261 0x30, 0x35, 0x2e, 0x33, 0x34, 0x32, 0x5a
262 ]
263 );
264
265 let data = [
267 24, 19, 43, 53, 49, 54, 49, 53, 32, 32, 48, 53, 50, 52, 48, 57, 52, 48, 50, 48, 90,
268 ];
269 assert!(crate::der::decode::<crate::types::Open>(&data).is_err());
270 assert!(crate::ber::decode::<crate::types::Open>(&data).is_err());
271
272 round_trip!(
274 ber,
275 GeneralizedTime,
276 GeneralizedTime::from(
277 NaiveDate::from_ymd_opt(2018, 1, 22)
278 .unwrap()
279 .and_hms_opt(13, 29, 0)
280 .unwrap()
281 .and_utc()
282 ),
283 &[
284 0x18, 0x0f, 0x32, 0x30, 0x31, 0x38, 0x30, 0x31, 0x32, 0x32, 0x31, 0x33, 0x32, 0x39,
285 0x30, 0x30, 0x5a
286 ]
287 );
288 round_trip!(
290 ber,
291 GeneralizedTime,
292 GeneralizedTime::from(
293 NaiveDate::from_ymd_opt(2018, 1, 22)
294 .unwrap()
295 .and_hms_opt(13, 0, 0)
296 .unwrap()
297 .and_utc()
298 ),
299 &[
300 0x18, 0x0f, 0x32, 0x30, 0x31, 0x38, 0x30, 0x31, 0x32, 0x32, 0x31, 0x33, 0x30, 0x30,
301 0x30, 0x30, 0x5a
302 ]
303 );
304
305 let offset = FixedOffset::east_opt(-3600 * 5).unwrap();
307 let dt1: DateTime<FixedOffset> = GeneralizedTime::from(DateTime::<Utc>::from(
308 NaiveDate::from_ymd_opt(2023, 1, 22)
309 .unwrap()
310 .and_hms_opt(13, 0, 0)
311 .unwrap()
312 .and_local_timezone(offset)
313 .unwrap(),
314 ));
315 round_trip!(
316 ber,
317 GeneralizedTime,
318 dt1,
319 &[
320 0x18, 0x0f, 0x32, 0x30, 0x32, 0x33, 0x30, 0x31, 0x32, 0x32, 0x31, 0x38, 0x30, 0x30,
321 0x30, 0x30, 0x5a
322 ]
323 );
324 let data = [
326 24, 19, 50, 48, 50, 51, 48, 49, 50, 50, 49, 51, 48, 48, 48, 48, 45, 48, 53, 48, 48,
327 ];
328 let result = crate::ber::decode::<crate::types::GeneralizedTime>(&data);
329 assert!(result.is_ok());
330 assert_eq!(dt1, result.unwrap());
331 }
332 #[test]
333 fn test_utc_time() {
334 round_trip!(
336 ber,
337 UtcTime,
338 UtcTime::from(
339 NaiveDate::from_ymd_opt(2018, 1, 22)
340 .unwrap()
341 .and_hms_opt(13, 29, 0)
342 .unwrap()
343 .and_utc()
344 ),
345 &[
346 0x17, 0x0d, 0x31, 0x38, 0x30, 0x31, 0x32, 0x32, 0x31, 0x33, 0x32, 0x39, 0x30, 0x30,
347 0x5a
348 ]
349 );
350 let offset = FixedOffset::east_opt(-3600 * 5).unwrap();
352 let dt1 = DateTime::<FixedOffset>::from_naive_utc_and_offset(
353 NaiveDate::from_ymd_opt(2023, 1, 22)
354 .unwrap()
355 .and_hms_opt(18, 0, 0)
356 .unwrap(),
357 offset,
358 );
359 round_trip!(
360 ber,
361 UtcTime,
362 dt1.into(),
363 &[
364 0x17, 0x0d, 0x32, 0x33, 0x30, 0x31, 0x32, 0x32, 0x31, 0x38, 0x30, 0x30, 0x30, 0x30,
365 0x5a
366 ]
367 );
368 let data = [
370 23, 17, 50, 51, 48, 49, 50, 50, 49, 51, 48, 48, 48, 48, 45, 48, 53, 48, 48,
371 ];
372 let result = crate::ber::decode::<crate::types::UtcTime>(&data);
373 assert!(result.is_ok());
374 assert_eq!(dt1, result.unwrap());
375 }
376}