1#![no_std]
2#![warn(missing_docs)]
3#![forbid(unsafe_code)]
4#![doc = include_str!("../README.md")]
5
6#[macro_use]
7extern crate alloc;
8
9use alloc::{borrow::ToOwned, vec::Vec};
10use core::{f64, num::FpCategory, str::FromStr};
11
12use facet_core::{
13 Def, Facet, NumericType, PrimitiveType, Shape, StructKind, TextualType, Type, UserType,
14};
15use facet_reflect::{HasFields, HeapValue, Partial, Peek};
16
17mod tag;
18
19const ASN1_TYPE_TAG_BOOLEAN: u8 = 0x01;
20const ASN1_TYPE_TAG_INTEGER: u8 = 0x02;
21const ASN1_TYPE_TAG_OCTET_STRING: u8 = 0x04;
22const ASN1_TYPE_TAG_NULL: u8 = 0x05;
23const ASN1_TYPE_TAG_REAL: u8 = 0x09;
24const ASN1_TYPE_TAG_UTF8STRING: u8 = 0x0C;
25const ASN1_TYPE_TAG_SEQUENCE: u8 = 0x10;
26
27const ASN1_FORM_CONSTRUCTED: u8 = 0b1 << 5;
28
29const ASN1_REAL_INFINITY: u8 = 0b01000000;
30const ASN1_REAL_NEG_INFINITY: u8 = 0b01000001;
31const ASN1_REAL_NAN: u8 = 0b01000010;
32const ASN1_REAL_NEG_ZERO: u8 = 0b01000011;
33
34const F64_MANTISSA_MASK: u64 = 0b1111111111111111111111111111111111111111111111111111;
35
36pub trait Asn1Write {
38 fn write(&mut self, buf: &[u8]);
40
41 fn reserve(&mut self, additional: usize);
43}
44
45impl Asn1Write for &mut Vec<u8> {
46 fn write(&mut self, buf: &[u8]) {
47 self.extend(buf)
48 }
49
50 fn reserve(&mut self, additional: usize) {
51 Vec::reserve(self, additional)
52 }
53}
54
55impl Asn1Write for Vec<u8> {
56 fn write(&mut self, buf: &[u8]) {
57 self.extend(buf)
58 }
59
60 fn reserve(&mut self, additional: usize) {
61 Vec::reserve(self, additional)
62 }
63}
64
65enum Asn1TagForShapeError {
66 TypeTag(tag::Asn1TagError),
67 UnsupportedShape,
68}
69
70fn ber_tag_for_shape(shape: &Shape) -> Result<Option<u8>, Asn1TagForShapeError> {
74 let type_tag = shape
75 .type_tag
76 .map(|t| tag::Asn1TypeTag::from_str(t).map_err(Asn1TagForShapeError::TypeTag))
77 .transpose()?
78 .map(|t| t.ber());
79 match (shape.def, shape.ty) {
80 (Def::Scalar, Type::Primitive(pt)) => match pt {
81 PrimitiveType::Boolean => Ok(Some(type_tag.unwrap_or(ASN1_TYPE_TAG_BOOLEAN))),
82 PrimitiveType::Numeric(nt) => match nt {
83 NumericType::Integer { .. } => Ok(Some(type_tag.unwrap_or(ASN1_TYPE_TAG_INTEGER))),
84 NumericType::Float => Ok(Some(type_tag.unwrap_or(ASN1_TYPE_TAG_REAL))),
85 },
86 PrimitiveType::Textual(TextualType::Str) => {
87 Ok(Some(type_tag.unwrap_or(ASN1_TYPE_TAG_UTF8STRING)))
88 }
89 _ => Err(Asn1TagForShapeError::UnsupportedShape),
90 },
91 (Def::Scalar, Type::User(UserType::Opaque)) => {
92 Ok(Some(type_tag.unwrap_or(ASN1_TYPE_TAG_UTF8STRING)))
93 }
94 (Def::List(ld), _) => {
95 if ld.t().is_type::<u8>() && shape.is_type::<Vec<u8>>() {
96 Ok(Some(type_tag.unwrap_or(ASN1_TYPE_TAG_OCTET_STRING)))
97 } else {
98 Ok(Some(
99 type_tag.unwrap_or(ASN1_TYPE_TAG_SEQUENCE) | ASN1_FORM_CONSTRUCTED,
100 ))
101 }
102 }
103 (Def::Option(od), _) => Ok(type_tag.or(ber_tag_for_shape(od.t)?)),
104 (_, Type::User(ut)) => match ut {
105 UserType::Struct(st) => match st.kind {
106 StructKind::Unit => Ok(Some(type_tag.unwrap_or(ASN1_TYPE_TAG_NULL))),
107 StructKind::TupleStruct if st.fields.len() == 1 && shape.is_transparent() => {
108 Ok(type_tag.or(ber_tag_for_shape(st.fields[0].shape())?))
109 }
110 StructKind::TupleStruct | StructKind::Struct | StructKind::Tuple => Ok(Some(
111 type_tag.unwrap_or(ASN1_TYPE_TAG_SEQUENCE) | ASN1_FORM_CONSTRUCTED,
112 )),
113 },
114 UserType::Enum(_) => {
115 Ok(None)
117 }
118 _ => Err(Asn1TagForShapeError::UnsupportedShape),
119 },
120 _ => Err(Asn1TagForShapeError::UnsupportedShape),
121 }
122}
123
124#[derive(Debug)]
125#[non_exhaustive]
126pub enum Asn1SerError {
128 TypeTag(tag::Asn1TagError),
130 UnsupportedShape,
132 InvalidDiscriminant(Option<i64>),
134}
135
136impl core::fmt::Display for Asn1SerError {
137 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
138 match self {
139 Asn1SerError::TypeTag(error) => write!(f, "Bad type_tag: {error}"),
140 Asn1SerError::UnsupportedShape => write!(f, "Unsupported shape"),
141 Asn1SerError::InvalidDiscriminant(d) => {
142 if let Some(d) = d {
143 write!(f, "Enum variant discriminant invalid: {d}")
144 } else {
145 write!(f, "Enum variant discriminant invalid")
146 }
147 }
148 }
149 }
150}
151
152impl core::error::Error for Asn1SerError {
153 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
154 match self {
155 Asn1SerError::TypeTag(error) => Some(error),
156 _ => None,
157 }
158 }
159}
160
161impl From<Asn1TagForShapeError> for Asn1SerError {
162 fn from(value: Asn1TagForShapeError) -> Self {
163 match value {
164 Asn1TagForShapeError::TypeTag(t) => Asn1SerError::TypeTag(t),
165 Asn1TagForShapeError::UnsupportedShape => Asn1SerError::UnsupportedShape,
166 }
167 }
168}
169
170pub fn to_vec_der<'f, F: Facet<'f>>(value: &'f F) -> Result<Vec<u8>, Asn1SerError> {
172 let mut buffer = Vec::new();
173 let peek = Peek::new(value);
174 let mut serializer = DerSerializer {
175 writer: &mut buffer,
176 };
177 serialize_der_recursive(peek, &mut serializer, None)?;
178 Ok(buffer)
179}
180
181struct DerSerializer<'w, W: Asn1Write> {
182 writer: &'w mut W,
183}
184
185impl<'w, W: Asn1Write> DerSerializer<'w, W> {
186 fn serialize_tlv(&mut self, tag: u8, value: &[u8]) {
187 if value.len() < 128 {
188 self.writer.write(&[tag, value.len() as u8]);
189 } else {
190 let len_bytes_len = core::cmp::max(value.len() / 256, 1);
191 let len_bytes = value.len().to_be_bytes();
192 self.writer.write(&[tag, len_bytes_len as u8]);
193 self.writer
194 .write(&len_bytes[len_bytes.len() - len_bytes_len..]);
195 }
196 self.writer.write(value);
197 }
198
199 fn serialize_i64(&mut self, tag: u8, value: i64) {
200 let bytes = value.to_be_bytes();
201 let mut leading_zeroes = 0;
202 for window in bytes.windows(2) {
203 let byte = window[0] as i8;
204 let bit = window[1] as i8 >> 7;
205 if byte ^ bit == 0 {
206 leading_zeroes += 1;
207 } else {
208 break;
209 }
210 }
211 self.serialize_tlv(tag, &bytes[leading_zeroes..])
212 }
213
214 fn serialize_f64(&mut self, tag: u8, value: f64) {
215 match value.classify() {
216 FpCategory::Nan => self.serialize_tlv(tag, &[ASN1_REAL_NAN]),
217 FpCategory::Infinite => {
218 if value.is_sign_positive() {
219 self.serialize_tlv(tag, &[ASN1_REAL_INFINITY])
220 } else {
221 self.serialize_tlv(tag, &[ASN1_REAL_NEG_INFINITY])
222 }
223 }
224 FpCategory::Zero | FpCategory::Subnormal => {
225 if value.is_sign_positive() {
227 self.serialize_unit(tag)
228 } else {
229 self.serialize_tlv(tag, &[ASN1_REAL_NEG_ZERO])
230 }
231 }
232 FpCategory::Normal => {
233 let sign_negative = value.is_sign_negative();
234 let bits = value.to_bits();
235 let mut exponent = ((bits >> 52) & 0b11111111111) as i16 - 1023;
237 let mut mantissa = bits & F64_MANTISSA_MASK | (0b1 << 52);
238 let mut normalization_factor = 52;
239 while mantissa & 0b1 == 0 {
240 mantissa >>= 1;
241 normalization_factor -= 1;
242 }
243 exponent -= normalization_factor;
244 let mantissa_bytes = mantissa.to_be_bytes();
245 let mut leading_zero_bytes = 0;
246 for byte in mantissa_bytes {
247 if byte == 0 {
248 leading_zero_bytes += 1;
249 } else {
250 break;
251 }
252 }
253 let exponent_bytes = exponent.to_be_bytes();
254 let short_exp = exponent_bytes[0] == 0 || exponent_bytes[0] == 0xFF;
256 let len = 2 + (!short_exp as usize) + mantissa_bytes.len() - leading_zero_bytes;
257 let structure_byte = 0b10000000 | ((sign_negative as u8) << 6) | (!short_exp as u8);
260 self.writer.write(&[tag, len as u8, structure_byte]);
261 if short_exp {
262 self.writer.write(&[exponent_bytes[1]]);
263 } else {
264 self.writer.write(&exponent_bytes);
265 }
266 self.writer.write(&mantissa_bytes[leading_zero_bytes..]);
267 }
268 }
269 }
270
271 fn serialize_bool(&mut self, tag: u8, value: bool) {
272 let byte = if value { 0xFF } else { 0x00 };
273 self.serialize_tlv(tag, &[byte])
274 }
275
276 fn serialize_str(&mut self, tag: u8, value: &str) {
277 self.serialize_tlv(tag, value.as_bytes())
278 }
279
280 fn serialize_unit(&mut self, tag: u8) {
281 self.serialize_tlv(tag, &[])
282 }
283}
284
285fn serialize_der_recursive<'w, W: Asn1Write>(
286 pv: Peek<'_, '_>,
287 serializer: &'w mut DerSerializer<'w, W>,
288 wrapper_tag: Option<u8>,
289) -> Result<(), Asn1SerError> {
290 let shape = pv.shape();
291 let tag = wrapper_tag.or(ber_tag_for_shape(shape)?);
292 match (shape.def, shape.ty) {
293 (Def::Scalar, Type::Primitive(pt)) => match pt {
294 PrimitiveType::Boolean => {
295 serializer.serialize_bool(tag.unwrap(), *pv.get::<bool>().unwrap());
296 Ok(())
297 }
298 PrimitiveType::Numeric(nt) => match nt {
299 NumericType::Integer { .. } => {
300 let value = if shape.is_type::<i8>() {
301 *pv.get::<i8>().unwrap() as i64
302 } else if shape.is_type::<i16>() {
303 *pv.get::<i16>().unwrap() as i64
304 } else if shape.is_type::<i32>() {
305 *pv.get::<i32>().unwrap() as i64
306 } else if shape.is_type::<i64>() {
307 *pv.get::<i64>().unwrap()
308 } else {
309 return Err(Asn1SerError::UnsupportedShape);
310 };
311 serializer.serialize_i64(tag.unwrap(), value);
312 Ok(())
313 }
314 NumericType::Float => {
315 let value = if shape.is_type::<f32>() {
316 *pv.get::<f32>().unwrap() as f64
317 } else if shape.is_type::<f64>() {
318 *pv.get::<f64>().unwrap()
319 } else {
320 return Err(Asn1SerError::UnsupportedShape);
321 };
322 serializer.serialize_f64(tag.unwrap(), value);
323 Ok(())
324 }
325 },
326 PrimitiveType::Textual(TextualType::Str) => {
327 let value = pv.get::<&str>().unwrap();
328 serializer.serialize_str(tag.unwrap(), value);
329 Ok(())
330 }
331 _ => Err(Asn1SerError::UnsupportedShape),
332 },
333 (Def::Scalar, Type::User(UserType::Opaque)) => {
334 if shape.vtable.has_display() {
335 serializer.serialize_str(tag.unwrap(), &alloc::format!("{pv}"));
336 Ok(())
337 } else {
338 Err(Asn1SerError::UnsupportedShape)
339 }
340 }
341 (Def::List(ld), _) => {
342 if ld.t().is_type::<u8>() && shape.is_type::<Vec<u8>>() {
343 serializer.serialize_tlv(tag.unwrap(), pv.get::<Vec<u8>>().unwrap());
344 } else {
345 let pv = pv.into_list().unwrap();
346 let mut value = Vec::new();
347 for pv in pv.iter() {
348 let mut inner_serializer = DerSerializer { writer: &mut value };
349 serialize_der_recursive(pv, &mut inner_serializer, None)?;
350 }
351 serializer.serialize_tlv(tag.unwrap(), &value);
352 }
353 Ok(())
354 }
355 (Def::Option(_), _) => {
356 let pv = pv.into_option().unwrap();
357 if let Some(pv) = pv.value() {
358 serialize_der_recursive(pv, serializer, tag)?;
359 }
360 Ok(())
361 }
362 (_, Type::User(ut)) => match ut {
363 UserType::Struct(st) => match st.kind {
364 StructKind::Unit => {
365 serializer.serialize_unit(tag.unwrap());
366 Ok(())
367 }
368 StructKind::TupleStruct if st.fields.len() == 1 && shape.is_transparent() => {
369 let inner = pv.into_struct().unwrap().field(0).unwrap();
370 serialize_der_recursive(inner, serializer, tag)
371 }
372 StructKind::TupleStruct | StructKind::Struct | StructKind::Tuple => {
373 let pv = pv.into_struct().unwrap();
374 let mut value = Vec::new();
375 for (_, pv) in pv.fields() {
376 let mut inner_serializer = DerSerializer { writer: &mut value };
377 serialize_der_recursive(pv, &mut inner_serializer, None)?;
378 }
379 serializer.serialize_tlv(tag.unwrap(), &value);
380 Ok(())
381 }
382 },
383 UserType::Enum(_) => {
384 let pv = pv.into_enum().unwrap();
385 let v = pv.active_variant().unwrap();
386 let discriminant = v.discriminant;
387 match v.data.kind {
388 StructKind::Unit => {
389 if discriminant
390 .is_some_and(|discriminant| !(0..128).contains(&discriminant))
391 {
392 return Err(Asn1SerError::InvalidDiscriminant(discriminant));
393 }
394 let tag = (discriminant.unwrap_or(ASN1_TYPE_TAG_NULL as i64) as u8)
395 | tag::ASN1_CLASS_CONTEXT_SPECIFIC;
396 serializer.serialize_unit(tag);
397 Ok(())
398 }
399 StructKind::TupleStruct if pv.fields().count() == 1 => {
400 let inner = pv.innermost_peek();
401 serialize_der_recursive(inner, serializer, None)
402 }
403 StructKind::TupleStruct | StructKind::Struct | StructKind::Tuple => {
404 if discriminant
405 .is_some_and(|discriminant| !(0..128).contains(&discriminant))
406 {
407 return Err(Asn1SerError::InvalidDiscriminant(discriminant));
408 }
409 let tag = (discriminant
410 .unwrap_or((ASN1_TYPE_TAG_SEQUENCE | ASN1_FORM_CONSTRUCTED) as i64)
411 as u8)
412 | tag::ASN1_CLASS_CONTEXT_SPECIFIC;
413 let mut value = Vec::new();
414 for (_, pv) in pv.fields() {
415 let mut inner_serializer = DerSerializer { writer: &mut value };
416 serialize_der_recursive(pv, &mut inner_serializer, None)?;
417 }
418 serializer.serialize_tlv(tag, &value);
419 Ok(())
420 }
421 }
422 }
423 _ => Err(Asn1SerError::UnsupportedShape),
424 },
425 _ => Err(Asn1SerError::UnsupportedShape),
426 }
427}
428
429#[derive(Debug)]
431pub enum Asn1DeserError {
432 TypeTag(tag::Asn1TagError),
434 UnsupportedShape,
436 UnknownTag {
438 tag: u8,
440 position: usize,
442 },
443 LengthMismatch {
445 len: usize,
447 expected_len: usize,
449 position: usize,
451 },
452 InvalidBool {
454 position: usize,
456 },
457 InvalidReal {
459 position: usize,
461 },
462 InvalidString {
464 position: usize,
466 source: core::str::Utf8Error,
468 },
469 SequenceSizeMismatch {
471 sequence_end: usize,
473 content_end: usize,
475 },
476}
477
478impl core::fmt::Display for Asn1DeserError {
479 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
480 match self {
481 Asn1DeserError::TypeTag(error) => write!(f, "Bad type_tag: {error}"),
482 Asn1DeserError::UnsupportedShape => write!(f, "Unsupported shape"),
483 Asn1DeserError::UnknownTag { tag, position } => {
484 write!(f, "Unknown tag {tag} at byte {position}")
485 }
486 Asn1DeserError::LengthMismatch {
487 len,
488 expected_len,
489 position,
490 } => {
491 write!(
492 f,
493 "Unexpected length {len} for type at byte {position}, expected {expected_len}",
494 )
495 }
496 Asn1DeserError::InvalidBool { position } => {
497 write!(f, "Invalid value for boolean at byte {position}")
498 }
499 Asn1DeserError::InvalidReal { position } => {
500 write!(f, "Invalid value for real at byte {position}")
501 }
502 Asn1DeserError::InvalidString { position, .. } => {
503 write!(f, "Invalid string at byte {position}")
504 }
505 Asn1DeserError::SequenceSizeMismatch {
506 sequence_end,
507 content_end,
508 } => {
509 write!(
510 f,
511 "Sequence ending at byte {sequence_end} didn't match content ending at byte {content_end}"
512 )
513 }
514 }
515 }
516}
517
518impl core::error::Error for Asn1DeserError {
519 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
520 match self {
521 Asn1DeserError::TypeTag(source) => Some(source),
522 Asn1DeserError::InvalidString { source, .. } => Some(source),
523 _ => None,
524 }
525 }
526}
527
528impl From<Asn1TagForShapeError> for Asn1DeserError {
529 fn from(value: Asn1TagForShapeError) -> Self {
530 match value {
531 Asn1TagForShapeError::TypeTag(t) => Asn1DeserError::TypeTag(t),
532 Asn1TagForShapeError::UnsupportedShape => Asn1DeserError::UnsupportedShape,
533 }
534 }
535}
536
537#[derive(Debug, Copy, Clone, PartialEq, Eq)]
538enum EncodingRules {
539 Distinguished,
542}
543
544#[derive(Debug, PartialEq)]
545enum PopReason {
546 TopLevel,
547 ObjectVal,
548 ListVal { end: usize },
549 Some,
550 Object { end: usize },
551}
552
553#[derive(Debug)]
554enum DeserializeTask {
555 Value { with_tag: Option<u8> },
556 Field(usize),
557 Pop(PopReason),
558}
559
560struct Asn1DeserializerStack<'input> {
561 _rules: EncodingRules,
562 input: &'input [u8],
563 pos: usize,
564 stack: Vec<DeserializeTask>,
565}
566
567impl<'input> Asn1DeserializerStack<'input> {
568 fn next_tl(&mut self, expected_tag: u8) -> Result<usize, Asn1DeserError> {
569 let tag = self.input[self.pos];
570 if tag != expected_tag {
571 return Err(Asn1DeserError::UnknownTag {
572 tag,
573 position: self.pos,
574 });
575 }
576 let len = self.input[self.pos + 1] as usize;
577 self.pos += 2;
578 let len = if len < 128 {
579 len
580 } else {
581 let len_len = len - 128;
582 self.pos += len_len;
583 let len_bytes = &self.input[(self.pos - len_len)..self.pos];
584 len_bytes.iter().fold(0usize, |mut acc, x| {
585 acc <<= 8;
586 acc += *x as usize;
587 acc
588 })
589 };
590 Ok(len)
591 }
592
593 fn next_tlv(&mut self, expected_tag: u8) -> Result<&'input [u8], Asn1DeserError> {
594 let len = self.next_tl(expected_tag)?;
595 self.pos += len;
596 Ok(&self.input[(self.pos - len)..self.pos])
597 }
598
599 fn next_bool(&mut self, tag: u8) -> Result<bool, Asn1DeserError> {
600 let bytes = self.next_tlv(tag)?;
601 match *bytes {
602 [0x00] => Ok(false),
603 [0xFF] => Ok(true),
604 [_] => Err(Asn1DeserError::InvalidBool { position: self.pos }),
605 _ => Err(Asn1DeserError::LengthMismatch {
606 len: bytes.len(),
607 expected_len: 1,
608 position: self.pos - bytes.len(),
609 }),
610 }
611 }
612
613 fn next_int(&mut self, tag: u8) -> Result<i64, Asn1DeserError> {
614 let bytes = self.next_tlv(tag)?;
615 Ok(bytes[1..].iter().fold(bytes[0] as i8 as i64, |mut acc, x| {
616 acc <<= 8;
617 acc |= *x as i64;
618 acc
619 }))
620 }
621
622 fn next_float(&mut self, tag: u8) -> Result<f64, Asn1DeserError> {
623 let bytes = self.next_tlv(tag)?;
624 Ok(if bytes.is_empty() {
625 0.0f64
626 } else {
627 match bytes[0] {
628 ASN1_REAL_INFINITY => f64::INFINITY,
629 ASN1_REAL_NEG_INFINITY => f64::NEG_INFINITY,
630 ASN1_REAL_NAN => f64::NAN,
631 ASN1_REAL_NEG_ZERO => -0.0f64,
632 struct_byte => {
633 if struct_byte & 0b10111100 != 0b10000000 {
634 return Err(Asn1DeserError::InvalidReal {
635 position: self.pos - bytes.len(),
636 });
637 }
638 let sign_negative = (struct_byte >> 6 & 0b1) > 0;
639 let exponent_len = ((struct_byte & 0b11) + 1) as usize;
640 if bytes.len() < exponent_len + 2 {
641 return Err(Asn1DeserError::LengthMismatch {
642 len: bytes.len(),
643 expected_len: exponent_len + 2,
644 position: self.pos - bytes.len(),
645 });
646 }
647 if exponent_len > 1 && matches!(bytes[1], 0x00 | 0xFF) {
648 return Err(Asn1DeserError::InvalidReal {
649 position: self.pos - bytes.len(),
650 });
651 }
652 if bytes.len() > 2 + exponent_len
653 && matches!(bytes[1 + exponent_len], 0x00 | 0xFF)
654 {
655 return Err(Asn1DeserError::InvalidReal {
656 position: self.pos - bytes.len(),
657 });
658 }
659 let mut exponent = bytes[2..1 + exponent_len].iter().fold(
660 bytes[1] as i8 as i64,
661 |mut acc, x| {
662 acc <<= 8;
663 acc |= *x as u64 as i64;
664 acc
665 },
666 );
667 if exponent > 1023 {
668 if sign_negative {
669 f64::NEG_INFINITY
670 } else {
671 f64::INFINITY
672 }
673 } else {
674 let mut mantissa =
675 bytes[1 + exponent_len..]
676 .iter()
677 .take(7)
678 .fold(0, |mut acc, x| {
679 acc <<= 8;
680 acc |= *x as u64;
681 acc
682 });
683 let mut normalization_factor = 52;
684 while mantissa & (0b1 << 52) == 0 && normalization_factor > 0 {
685 mantissa <<= 1;
686 normalization_factor -= 1;
687 }
688 exponent += normalization_factor + 1023;
689 f64::from_bits(
690 (sign_negative as u64) << 63
691 | ((exponent as u64) & 0b11111111111) << 52
692 | (mantissa & F64_MANTISSA_MASK),
693 )
694 }
695 }
696 }
697 })
698 }
699
700 fn next_str(&mut self, tag: u8) -> Result<&str, Asn1DeserError> {
701 let bytes = self.next_tlv(tag)?;
702 core::str::from_utf8(bytes).map_err(|source| Asn1DeserError::InvalidString {
703 position: self.pos,
704 source,
705 })
706 }
707
708 fn next<'f>(
709 &mut self,
710 wip: Partial<'f>,
711 with_tag: Option<u8>,
712 ) -> Result<Partial<'f>, Asn1DeserError> {
713 let shape = wip.shape();
714 let tag_for_shape = with_tag.or(ber_tag_for_shape(shape)?);
715 match (shape.def, shape.ty) {
716 (Def::Scalar, Type::Primitive(pt)) => match pt {
717 PrimitiveType::Boolean => {
718 let wip = wip.set(self.next_bool(tag_for_shape.unwrap())?).unwrap();
719 Ok(wip)
720 }
721 PrimitiveType::Numeric(nt) => match nt {
722 NumericType::Integer { .. } => {
723 let number = self.next_int(tag_for_shape.unwrap())?;
724 let wip = if shape.is_type::<i8>() {
725 wip.set(number as i8).unwrap()
726 } else if shape.is_type::<i16>() {
727 wip.set(number as i16).unwrap()
728 } else if shape.is_type::<i32>() {
729 wip.set(number as i32).unwrap()
730 } else if shape.is_type::<i64>() {
731 wip.set(number).unwrap()
732 } else {
733 wip
734 };
735 Ok(wip)
736 }
737 NumericType::Float => {
738 let value = self.next_float(tag_for_shape.unwrap())?;
739 let wip = if shape.is_type::<f32>() {
740 wip.set(value as f32).unwrap()
741 } else if shape.is_type::<f64>() {
742 wip.set(value).unwrap()
743 } else {
744 wip
745 };
746 Ok(wip)
747 }
748 },
749 PrimitiveType::Textual(TextualType::Str) => {
750 let value = self.next_str(tag_for_shape.unwrap())?;
751 let wip = wip.set(value.to_owned()).unwrap();
752 Ok(wip)
753 }
754 _ => Err(Asn1DeserError::UnsupportedShape),
755 },
756 (Def::Scalar, Type::User(UserType::Opaque)) => {
757 if shape.vtable.has_parse() {
758 let value = self.next_str(tag_for_shape.unwrap())?.to_owned();
759 let wip = wip.set(value).unwrap();
760 Ok(wip)
761 } else {
762 Err(Asn1DeserError::UnsupportedShape)
763 }
764 }
765 (Def::List(_), _) => {
766 if shape.is_type::<Vec<u8>>() {
767 let bytes = self.next_tlv(tag_for_shape.unwrap())?;
768 let wip = wip.set(bytes.to_vec()).unwrap();
769 Ok(wip)
770 } else {
771 let len = self.next_tl(tag_for_shape.unwrap())?;
772 self.stack.push(DeserializeTask::Pop(PopReason::ListVal {
773 end: self.pos + len,
774 }));
775 self.stack.push(DeserializeTask::Value { with_tag: None });
776 Ok(wip)
777 }
778 }
779 (Def::Option(od), _) => {
780 if self.pos == self.input.len() {
781 let wip = wip.set_default().unwrap();
782 return Ok(wip);
783 }
784 let tag = self.input[self.pos];
785 let wip = match tag_for_shape {
786 Some(t) if t == tag => {
787 let wip = wip.begin_some().unwrap();
788 self.stack.push(DeserializeTask::Pop(PopReason::Some));
789 self.stack
790 .push(DeserializeTask::Value { with_tag: Some(t) });
791 wip
792 }
793 Some(_) => wip.set_default().unwrap(),
794 None => {
795 if let Type::User(UserType::Enum(et)) = od.t.ty {
796 let mut found = false;
797 for v in et.variants {
798 if let Some(variant_tag) = match v.data.kind {
799 StructKind::Tuple if v.data.fields.len() == 1 => {
800 ber_tag_for_shape(v.data.fields[0].shape())?
801 }
802 StructKind::Unit
803 | StructKind::TupleStruct
804 | StructKind::Struct
805 | StructKind::Tuple => v.discriminant.map(|discriminant| {
806 discriminant as u8 | tag::ASN1_CLASS_CONTEXT_SPECIFIC
807 }),
808 } && tag == variant_tag
809 {
810 found = true;
811 break;
812 }
813 }
814 if found {
815 let wip = wip.begin_some().unwrap();
816 self.stack.push(DeserializeTask::Pop(PopReason::Some));
817 self.stack.push(DeserializeTask::Value { with_tag: None });
818 wip
819 } else {
820 wip.set_default().unwrap()
821 }
822 } else {
823 wip.set_default().unwrap()
824 }
825 }
826 };
827 Ok(wip)
828 }
829 (_, Type::User(ut)) => match ut {
830 UserType::Struct(st) => match st.kind {
831 StructKind::Unit => {
832 let len = self.next_tl(tag_for_shape.unwrap())?;
833 if len != 0 {
834 Err(Asn1DeserError::LengthMismatch {
835 len,
836 expected_len: 0,
837 position: self.pos,
838 })
839 } else {
840 Ok(wip)
841 }
842 }
843 StructKind::TupleStruct if st.fields.len() == 1 && shape.is_transparent() => {
844 let wip = wip.begin_nth_field(0).unwrap();
845 self.stack.push(DeserializeTask::Pop(PopReason::ObjectVal));
846 self.stack.push(DeserializeTask::Value {
847 with_tag: tag_for_shape,
848 });
849 Ok(wip)
850 }
851 StructKind::TupleStruct | StructKind::Struct | StructKind::Tuple => {
852 let len = self.next_tl(tag_for_shape.unwrap())?;
853 self.stack.push(DeserializeTask::Pop(PopReason::Object {
854 end: self.pos + len,
855 }));
856 for i in (0..st.fields.len()).rev() {
857 self.stack.push(DeserializeTask::Field(i));
858 }
859 Ok(wip)
860 }
861 },
862 UserType::Enum(et) => {
863 let tag = self.input[self.pos];
864 for (i, v) in et.variants.iter().enumerate() {
865 match v.data.kind {
866 StructKind::Unit => {
867 if let Some(discriminant) = v.discriminant {
868 let expected_tag =
869 discriminant as u8 | tag::ASN1_CLASS_CONTEXT_SPECIFIC;
870 if tag == expected_tag {
871 let wip = wip.select_nth_variant(i).unwrap();
872 let len = self.next_tl(tag)?;
873 if len != 0 {
874 return Err(Asn1DeserError::LengthMismatch {
875 len,
876 expected_len: 0,
877 position: self.pos,
878 });
879 } else {
880 return Ok(wip);
881 }
882 }
883 }
884 }
885 StructKind::Tuple if v.data.fields.len() == 1 => {
886 let inner_tag = ber_tag_for_shape(v.data.fields[0].shape())?;
887 if inner_tag.is_some_and(|vtag| vtag == tag) {
888 let wip = wip.select_nth_variant(i).unwrap();
889 self.stack.push(DeserializeTask::Pop(PopReason::ObjectVal));
890 self.stack.push(DeserializeTask::Value { with_tag: None });
891 return Ok(wip);
892 }
893 }
894 StructKind::TupleStruct | StructKind::Struct | StructKind::Tuple => {
895 if let Some(discriminant) = v.discriminant {
896 let expected_tag =
897 discriminant as u8 | tag::ASN1_CLASS_CONTEXT_SPECIFIC;
898 if tag == expected_tag {
899 let wip = wip.select_nth_variant(i).unwrap();
900 let len = self.next_tl(tag)?;
901 self.stack.push(DeserializeTask::Pop(PopReason::Object {
902 end: self.pos + len,
903 }));
904 for i in (0..v.data.fields.len()).rev() {
905 self.stack.push(DeserializeTask::Field(i));
906 }
907 return Ok(wip);
908 }
909 }
910 }
911 }
912 }
913 Err(Asn1DeserError::UnknownTag {
914 tag,
915 position: self.pos,
916 })
917 }
918 _ => Err(Asn1DeserError::UnsupportedShape),
919 },
920 _ => Err(Asn1DeserError::UnsupportedShape),
921 }
922 }
923}
924
925pub fn deserialize_der_wip<'facet>(
927 input: &[u8],
928 wip: Partial<'facet>,
929) -> Result<HeapValue<'facet>, Asn1DeserError> {
930 let mut runner = Asn1DeserializerStack {
931 _rules: EncodingRules::Distinguished,
932 input,
933 pos: 0,
934 stack: vec![
935 DeserializeTask::Pop(PopReason::TopLevel),
936 DeserializeTask::Value { with_tag: None },
937 ],
938 };
939
940 let mut wip = wip;
941 loop {
942 match runner.stack.pop() {
943 Some(DeserializeTask::Pop(reason)) => match reason {
944 PopReason::TopLevel => {
945 return Ok(wip.build().unwrap());
946 }
947 PopReason::Object { end } => {
948 if runner.pos != end {
949 return Err(Asn1DeserError::SequenceSizeMismatch {
950 sequence_end: end,
951 content_end: runner.pos,
952 });
953 }
954 }
955 PopReason::ListVal { end } => {
956 if runner.pos < end {
957 runner
958 .stack
959 .push(DeserializeTask::Pop(PopReason::ListVal { end }));
960 runner.stack.push(DeserializeTask::Value { with_tag: None });
961 } else if runner.pos > end {
962 return Err(Asn1DeserError::SequenceSizeMismatch {
963 sequence_end: end,
964 content_end: runner.pos,
965 });
966 }
967 }
968 _ => {
969 wip = wip.end().unwrap();
970 }
971 },
972 Some(DeserializeTask::Value { with_tag }) => {
973 wip = runner.next(wip, with_tag)?;
974 }
975 Some(DeserializeTask::Field(index)) => {
976 runner
977 .stack
978 .push(DeserializeTask::Pop(PopReason::ObjectVal));
979 runner.stack.push(DeserializeTask::Value { with_tag: None });
980 wip = wip.begin_nth_field(index).unwrap();
981 }
982 None => unreachable!("Instruction stack is empty"),
983 }
984 }
985}
986
987pub fn deserialize_der<'f, F: facet_core::Facet<'f>>(input: &[u8]) -> Result<F, Asn1DeserError> {
989 let v = deserialize_der_wip(input, Partial::alloc_shape(F::SHAPE).unwrap())?;
990 let f: F = v.materialize().unwrap();
991 Ok(f)
992}