Skip to main content

facet_asn1/
lib.rs

1//! ASN.1 DER/BER serialization and deserialization for facet.
2//!
3//! This crate provides ASN.1 DER (Distinguished Encoding Rules) support via the
4//! `FormatParser` and `FormatSerializer` traits.
5//!
6//! # ASN.1 Overview
7//!
8//! ASN.1 (Abstract Syntax Notation One) is a standard interface description language
9//! for defining data structures that can be serialized and deserialized in a
10//! cross-platform way. DER is a specific encoding rule that ensures canonical encoding.
11//!
12//! # Serialization
13//!
14//! ```
15//! use facet::Facet;
16//! use facet_asn1::to_vec;
17//!
18//! #[derive(Facet)]
19//! struct Point { x: i32, y: i32 }
20//!
21//! let point = Point { x: 10, y: 20 };
22//! let bytes = to_vec(&point).unwrap();
23//! ```
24//!
25//! # Deserialization
26//!
27//! ```ignore
28//! use facet::Facet;
29//! use facet_asn1::from_slice;
30//!
31//! #[derive(Facet)]
32//! struct Point { x: i32, y: i32 }
33//!
34//! // DER encoding of Point { x: 10, y: 20 }
35//! let bytes = &[0x30, 0x06, 0x02, 0x01, 0x0A, 0x02, 0x01, 0x14];
36//! let point: Point = from_slice(bytes).unwrap();
37//! ```
38//!
39//! # Type Mapping
40//!
41//! | Rust Type | ASN.1 Type |
42//! |-----------|------------|
43//! | `bool` | BOOLEAN |
44//! | `i8`, `i16`, `i32`, `i64` | INTEGER |
45//! | `u8`, `u16`, `u32`, `u64` | INTEGER |
46//! | `f32`, `f64` | REAL |
47//! | `String`, `&str` | UTF8String |
48//! | `Vec<u8>`, `&[u8]` | OCTET STRING |
49//! | struct | SEQUENCE |
50//! | `Vec<T>` | SEQUENCE OF |
51//! | `Option<T>` | Optional field |
52//! | `()` | NULL |
53
54#![cfg_attr(not(feature = "std"), no_std)]
55
56extern crate alloc;
57
58mod error;
59mod parser;
60mod serializer;
61
62pub use error::{Asn1Error, Asn1ErrorKind};
63pub use parser::Asn1Parser;
64pub use serializer::{Asn1SerializeError, Asn1Serializer, to_vec};
65
66// Re-export DeserializeError for convenience
67pub use facet_format::DeserializeError;
68
69/// Deserialize a value from ASN.1 DER bytes into an owned type.
70///
71/// This is the recommended default for most use cases. The input does not need
72/// to outlive the result, making it suitable for deserializing from temporary
73/// buffers.
74///
75/// # Example
76///
77/// ```ignore
78/// use facet::Facet;
79/// use facet_asn1::from_slice;
80///
81/// #[derive(Facet, Debug, PartialEq)]
82/// struct Point {
83///     x: i32,
84///     y: i32,
85/// }
86///
87/// // DER encoding of Point { x: 10, y: 20 }
88/// let bytes = &[0x30, 0x06, 0x02, 0x01, 0x0A, 0x02, 0x01, 0x14];
89/// let point: Point = from_slice(bytes).unwrap();
90/// assert_eq!(point.x, 10);
91/// assert_eq!(point.y, 20);
92/// ```
93pub fn from_slice<T>(input: &[u8]) -> Result<T, DeserializeError<Asn1Error>>
94where
95    T: facet_core::Facet<'static>,
96{
97    use facet_format::FormatDeserializer;
98    let parser = Asn1Parser::new(input);
99    let mut de = FormatDeserializer::new_owned(parser);
100    de.deserialize()
101}
102
103/// Deserialize a value from ASN.1 DER bytes, allowing zero-copy borrowing.
104///
105/// This variant requires the input to outlive the result (`'input: 'facet`),
106/// enabling zero-copy deserialization of byte slices as `&[u8]` or `Cow<[u8]>`.
107///
108/// Use this when you need maximum performance and can guarantee the input
109/// buffer outlives the deserialized value.
110pub fn from_slice_borrowed<'input, 'facet, T>(
111    input: &'input [u8],
112) -> Result<T, DeserializeError<Asn1Error>>
113where
114    T: facet_core::Facet<'facet>,
115    'input: 'facet,
116{
117    use facet_format::FormatDeserializer;
118    let parser = Asn1Parser::new(input);
119    let mut de = FormatDeserializer::new(parser);
120    de.deserialize()
121}