Skip to main content

picky_asn1_der/
lib.rs

1//! [![Crates.io](https://img.shields.io/crates/v/picky-asn1-der.svg)](https://crates.io/crates/picky-asn1-der)
2//! [![docs.rs](https://docs.rs/picky-asn1-der/badge.svg)](https://docs.rs/picky-asn1-der)
3//! ![Crates.io](https://img.shields.io/crates/l/picky-asn1-der)
4//!
5//! # picky-asn1-der
6//!
7//! Portions of project [serde_asn1_der](https://github.com/KizzyCode/serde_asn1_der) are held by
8//! Keziah Biermann, 2019 as part of this project.
9//!
10//! This crate implements an ASN.1-DER subset for serde.
11//!
12//! The following types have built-in support:
13//! - `bool`: The ASN.1-BOOLEAN-type
14//! - `u8`, `u16`, `u32`, `u64`, `u128`, `usize`: The ASN.1-INTEGER-type
15//! - `()`: The ASN.1-NULL-type
16//! - `&[u8]`, `Vec<u8>`: The ASN.1-OctetString-type
17//! - `&str`, `String`: The ASN.1-UTF8String-type
18//!
19//! More advanced types are supported through wrappers:
20//! - Integer (as big integer)
21//! - Bit String
22//! - Object Identifier
23//! - Utf8 String
24//! - Numeric String
25//! - Printable String
26//! - IA5 String
27//! - Generalized Time
28//! - UTC Time
29//! - Application Tags from 0 to 15
30//! - Context Tags from 0 to 15
31//!
32//! Everything sequence-like combined out of this types is also supported out of the box.
33//!
34//! ```rust
35//! use serde::{Serialize, Deserialize};
36//!
37//! #[derive(Serialize, Deserialize)] // Now our struct supports all DER-conversion-traits
38//! struct Address {
39//!     street: String,
40//!     house_number: u128,
41//!     postal_code: u128,
42//!     state: String,
43//!     country: String
44//! }
45//!
46//! #[derive(Serialize, Deserialize)] // Now our struct supports all DER-conversion-traits too
47//! struct Customer {
48//!     name: String,
49//!     e_mail_address: String,
50//!     postal_address: Address
51//! }
52//! ```
53//!
54//!
55//! # Example
56//! ```rust
57//! use serde::{Serialize, Deserialize};
58//!
59//! #[derive(Serialize, Deserialize)]
60//! struct TestStruct {
61//!     number: u8,
62//!     #[serde(with = "serde_bytes")]
63//!     vec: Vec<u8>,
64//!     tuple: (usize, ())
65//! }
66//!
67//! let plain = TestStruct{ number: 7, vec: b"Testolope".to_vec(), tuple: (4, ()) };
68//! let serialized = picky_asn1_der::to_vec(&plain).unwrap();
69//! let deserialized: TestStruct = picky_asn1_der::from_bytes(&serialized).unwrap();
70//! ```
71
72#[macro_use]
73mod debug_log;
74
75pub mod application_tag;
76mod de;
77pub(crate) mod misc;
78mod raw_der;
79mod ser;
80
81pub use crate::de::{Deserializer, from_bytes, from_reader, from_reader_with_max_len};
82pub use crate::raw_der::Asn1RawDer;
83pub use crate::ser::{Serializer, to_byte_buf, to_bytes, to_vec, to_writer};
84
85use std::error::Error;
86use std::fmt::{self, Display, Formatter};
87use std::io;
88
89/// A `picky_asn1_der`-related error
90#[derive(Debug)]
91pub enum Asn1DerError {
92    /// The data is truncated
93    TruncatedData,
94
95    /// The data is invalid
96    InvalidData,
97
98    /// The value may be valid but is unsupported (e.g. an integer that is too large)
99    UnsupportedValue,
100
101    /// The data type is not supported by the (de-)serializer
102    UnsupportedType,
103
104    /// The provided sink is unable to accept all bytes
105    InvalidSink,
106
107    /// A custom message produced by `serde`
108    Message(String),
109
110    /// Some other underlying error (e.g. an IO error)
111    Other(Box<dyn Error + Send + Sync + 'static>),
112}
113
114impl Display for Asn1DerError {
115    fn fmt(&self, t: &mut Formatter) -> fmt::Result {
116        write!(t, "{self:?}")
117    }
118}
119
120impl Error for Asn1DerError {
121    fn source(&self) -> Option<&(dyn Error + 'static)> {
122        match self {
123            Asn1DerError::Other(source) => Some(source.as_ref()),
124            _ => None,
125        }
126    }
127}
128
129impl serde::de::Error for Asn1DerError {
130    fn custom<T: Display>(msg: T) -> Self {
131        Asn1DerError::Message(msg.to_string())
132    }
133}
134
135impl serde::ser::Error for Asn1DerError {
136    fn custom<T: Display>(msg: T) -> Self {
137        Asn1DerError::Message(msg.to_string())
138    }
139}
140
141impl From<io::Error> for Asn1DerError {
142    fn from(io_error: io::Error) -> Self {
143        match io_error.kind() {
144            io::ErrorKind::UnexpectedEof => Asn1DerError::TruncatedData,
145            io::ErrorKind::WriteZero => Asn1DerError::InvalidSink,
146            _ => Asn1DerError::Other(Box::new(io_error)),
147        }
148    }
149}
150
151pub type Result<T> = std::result::Result<T, Asn1DerError>;