yasna/
lib.rs

1// Copyright 2016 Masaki Hara
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! A library for reading and writing ASN.1 data.
10//!
11//! # Examples
12//!
13//! ## Encoding/decoding simple data
14//!
15//! A type implementing [`DEREncodable`] can be easily encoded:
16//!
17//! ```
18//! fn main() {
19//!     let der = yasna::encode_der(&(10, true));
20//!     println!("(10, true) = {:?}", der);
21//! }
22//! ```
23//!
24//! Similarly, a type implementing [`BERDecodable`] can be
25//! easily decoded:
26//!
27//! ```
28//! fn main() {
29//!     let asn: (i64, bool) = yasna::decode_der(
30//!         &[48, 6, 2, 1, 10, 1, 1, 255]).unwrap();
31//!     println!("{:?} = [48, 6, 2, 1, 10, 1, 1, 255]", asn);
32//! }
33//! ```
34//!
35//! ## Encoding/decoding by hand
36//!
37//! The default [`DEREncodable`]/[`BERDecodable`] implementations can't handle
38//! all ASN.1 types. In many cases you have to write your reader/writer
39//! by hand.
40//!
41//! To serialize ASN.1 data, you can use [`construct_der`].
42//!
43//! ```
44//! fn main() {
45//!     let der = yasna::construct_der(|writer| {
46//!         writer.write_sequence(|writer| {
47//!             writer.next().write_i64(10);
48//!             writer.next().write_bool(true);
49//!         })
50//!     });
51//!     println!("(10, true) = {:?}", der);
52//! }
53//! ```
54//!
55//! To deserialize ASN.1 data, you can use [`parse_ber`] or [`parse_der`].
56//!
57//! ```
58//! fn main() {
59//!     let asn = yasna::parse_der(&[48, 6, 2, 1, 10, 1, 1, 255], |reader| {
60//!         reader.read_sequence(|reader| {
61//!             let i = reader.next().read_i64()?;
62//!             let b = reader.next().read_bool()?;
63//!             return Ok((i, b));
64//!         })
65//!     }).unwrap();
66//!     println!("{:?} = [48, 6, 2, 1, 10, 1, 1, 255]", asn);
67//! }
68//! ```
69
70#![forbid(unsafe_code)]
71#![deny(missing_docs)]
72#![no_std]
73
74extern crate alloc;
75#[cfg(any(test, feature = "std"))]
76extern crate std;
77
78pub mod tags;
79pub mod models;
80mod writer;
81mod reader;
82mod deserializer;
83mod serializer;
84
85pub use crate::writer::{construct_der,try_construct_der};
86pub use crate::writer::{construct_der_seq,try_construct_der_seq};
87pub use crate::writer::{DERWriter,DERWriterSeq,DERWriterSet};
88pub use crate::reader::{parse_ber_general,parse_ber,parse_der,BERMode};
89pub use crate::reader::{BERReader,BERReaderSeq,BERReaderSet};
90pub use crate::reader::{ASN1Error,ASN1ErrorKind,ASN1Result};
91pub use crate::deserializer::{BERDecodable,decode_ber_general,decode_ber,decode_der};
92pub use crate::serializer::{DEREncodable,encode_der};
93
94/// A value of the ASN.1 primitive/constructed ("P/C") bit.
95#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
96pub enum PCBit {
97    /// The bit's value is "Primitive"
98    Primitive = 0,
99    /// The bit's value is "Constructed"
100    Constructed = 1,
101}
102
103/// An ASN.1 tag class, used in [`Tag`].
104///
105/// A tag class is one of:
106///
107/// - UNIVERSAL
108/// - APPLICATION
109/// - context specific
110/// - PRIVATE
111#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
112pub enum TagClass {
113    /// The UNIVERSAL tag class
114    Universal = 0,
115    /// The APPLICATION tag class
116    Application = 1,
117    /// The CONTEXT-SPECIFIC tag class
118    ContextSpecific = 2,
119    /// The PRIVATE tag class
120    Private = 3,
121}
122
123const TAG_CLASSES : [TagClass; 4] = [
124    TagClass::Universal,
125    TagClass::Application,
126    TagClass::ContextSpecific,
127    TagClass::Private,
128];
129
130/// An ASN.1 tag.
131///
132/// An ASN.1 tag is a pair of a tag class and a tag number.
133///
134/// - A tag class is one of:
135///   - UNIVERSAL
136///   - APPLICATION
137///   - context specific
138///   - PRIVATE
139/// - A tag number is a nonnegative integer.
140///   In this library, tag numbers are assumed to fit into `u64`.
141#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
142pub struct Tag {
143    /// The tag class
144    pub tag_class: TagClass,
145    /// The tag number
146    pub tag_number: u64,
147}
148
149impl Tag {
150    /// Constructs an APPLICATION tag, namely \[APPLICATION n\].
151    pub fn application(tag_number: u64) -> Tag {
152        return Tag {
153            tag_class: TagClass::Application,
154            tag_number,
155        }
156    }
157    /// Constructs a context specific tag, namely \[n\].
158    pub fn context(tag_number: u64) -> Tag {
159        return Tag {
160            tag_class: TagClass::ContextSpecific,
161            tag_number,
162        }
163    }
164    /// Constructs a PRIVATE tag, namely \[PRIVATE n\].
165    pub fn private(tag_number: u64) -> Tag {
166        return Tag {
167            tag_class: TagClass::Private,
168            tag_number,
169        }
170    }
171}