facet_asn1_legacy/
lib.rs

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
36/// `no_std` compatible Write trait used by the ASN.1 serializer.
37pub trait Asn1Write {
38    /// Write all these bytes to the writer.
39    fn write(&mut self, buf: &[u8]);
40
41    /// If the writer supports it, reserve space for `len` additional bytes.
42    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
70/// Get the BER/DER tag for a given shape
71///
72/// Returns `None` for CHOICE/Enum
73fn 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                // Enum variants are matched against their discriminant or inner types
116                Ok(None)
117            }
118            _ => Err(Asn1TagForShapeError::UnsupportedShape),
119        },
120        _ => Err(Asn1TagForShapeError::UnsupportedShape),
121    }
122}
123
124#[derive(Debug)]
125#[non_exhaustive]
126/// Errors when serializing to an ASN.1 format
127pub enum Asn1SerError {
128    /// Invalid type tag
129    TypeTag(tag::Asn1TagError),
130    /// Unsupported shape
131    UnsupportedShape,
132    /// Enum unit variant discriminant too large
133    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
170/// Serialize a Facet type to ASN.1 DER bytes
171pub 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                // Subnormals cannot be represented in DER and are rounded to zero
226                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                // The exponent is always 11 bits in f64, so we can fit it inside an i16.
236                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                // If the exponent can be represented as an i8, then we must do so.
255                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                // This identifying byte contains the encoding method, as well as the sign and
258                // exponent length.
259                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/// Errors when deserializing from ASN.1 BER or DER bytes
430#[derive(Debug)]
431pub enum Asn1DeserError {
432    /// Invalid type tag
433    TypeTag(tag::Asn1TagError),
434    /// Unsupported shape
435    UnsupportedShape,
436    /// Tag couldn't be matched to a struct, field, or enum variant
437    UnknownTag {
438        /// Tag value
439        tag: u8,
440        /// Position of this error in bytes
441        position: usize,
442    },
443    /// Unexpected length for type
444    LengthMismatch {
445        /// Length value
446        len: usize,
447        /// Expected length value
448        expected_len: usize,
449        /// Position of this error in bytes
450        position: usize,
451    },
452    /// Invalid boolean
453    InvalidBool {
454        /// Position of this error in bytes
455        position: usize,
456    },
457    /// Invalid real
458    InvalidReal {
459        /// Position of this error in bytes
460        position: usize,
461    },
462    /// Invalid string
463    InvalidString {
464        /// Position of this error in bytes
465        position: usize,
466        /// Underlying UTF-8 error
467        source: core::str::Utf8Error,
468    },
469    /// Sequence length didn't match content length
470    SequenceSizeMismatch {
471        /// Position of the end of the sequence in bytes
472        sequence_end: usize,
473        /// Position of the end of the sequence content
474        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    // Basic,
540    // Canonical,
541    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
925/// Deserialize an ASN.1 DER slice given some some [`Partial`] into a [`HeapValue`]
926pub 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
987/// Deserialize a slice of ASN.1 DER bytes into a Facet type
988pub 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}