Skip to content

Commit 1802e36

Browse files
committedApr 16, 2025·
Part one of improving decoding.
1 parent a25d3e8 commit 1802e36

File tree

7 files changed

+1650
-2222
lines changed

7 files changed

+1650
-2222
lines changed
 

‎Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "bcder"
33
version = "0.7.6-dev"
4-
edition = "2018"
4+
edition = "2021"
55
authors = ["NLnet Labs <rust-team@nlnetlabs.nl>"]
66
description = "Handling of data encoded in BER, CER, and DER."
77
documentation = "https://docs.rs/bcder/"

‎src/decode/content.rs

Lines changed: 580 additions & 902 deletions
Large diffs are not rendered by default.

‎src/decode/mod.rs

Lines changed: 6 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,12 @@
1-
//! Parsing BER-encoded data.
2-
//!
3-
//! This modules provides the means to parse BER-encoded data.
4-
//!
5-
//! The basic idea is that for each type a function exists that knows how
6-
//! to decode one value of that type. For constructed types, this function
7-
//! in turn relies on similar functions provided for its constituent types.
8-
//! For a detailed introduction to how to write these functions, please
9-
//! refer to the [decode section of the guide][crate::guide::decode].
10-
//!
11-
//! The two most important types of this module are [`Primitive`] and
12-
//! [`Constructed`], representing the content octets of a value in primitive
13-
//! and constructed encoding, respectively. Each provides a number of methods
14-
//! allowing to parse the content.
15-
//!
16-
//! You will never create a value of either type. Rather, you get handed a
17-
//! reference to one as an argument to a closure or function argument to be
18-
//! provided to these methods.
19-
//!
20-
//! The enum [`Content`] is used for cases where a value can be either
21-
//! primitive or constructed such as most string types.
22-
//!
23-
//! The data for decoding is provided by any type that implements the
24-
//! [`Source`] trait – or can be converted into such a type via the
25-
//! [`IntoSource`] trait. Implementations for both `bytes::Bytes` and
26-
//! `&[u8]` are available.
27-
//!
28-
//! During decoding, errors can happen. There are two kinds of errors: for
29-
//! one, the source can fail to gather more data, e.g., when reading from a
30-
//! file fails. Such errors are called _source errors._ Their type is
31-
//! provided by the source.
32-
//!
33-
//! Second, data that cannot be decoded according to the syntax is said to
34-
//! result in a _content error._ The [`ContentError`] type is used for such
35-
//! errors.
36-
//!
37-
//! When decoding data from a source, both errors can happen. The type
38-
//! `DecodeError` provides a way to store either of them and is the error
39-
//! type you will likely encounter the most.
40-
41-
pub use self::content::{Content, Constructed, Primitive};
1+
//pub use self::content::{Content, Constructed, Primitive};
422
pub use self::error::{ContentError, DecodeError};
433
pub use self::source::{
44-
BytesSource, CaptureSource, IntoSource, Pos, LimitedSource, SliceSource,
4+
Fragment, Pos, ReaderFragment, ReaderSource, SliceFragment, SliceSource,
455
Source
466
};
477

48-
mod content;
49-
mod error;
50-
mod source;
8+
9+
pub mod content;
10+
pub mod error;
11+
pub mod source;
5112

‎src/decode/source.rs

Lines changed: 240 additions & 606 deletions
Large diffs are not rendered by default.

‎src/length.rs

Lines changed: 363 additions & 185 deletions
Large diffs are not rendered by default.

‎src/mode.rs

Lines changed: 53 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,69 @@
11
//! The BER mode.
22
//!
3-
//! This is a private module. It’s public items are re-exported by the parent.
3+
//!
44
5-
use crate::decode;
6-
use crate::decode::DecodeError;
75

6+
/// Basic Encoding Rules.
7+
///
8+
/// These are the most flexible rules, allowing alternative encodings for
9+
/// some types as well as indefinite length values.
10+
//
11+
// XXX We derive all the things for now so we can derive them on types that
12+
// are generic over the mode but will replace the derives later.
13+
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
14+
pub struct Ber;
815

9-
//------------ Mode ----------------------------------------------------------
10-
11-
/// The BER Mode.
16+
/// Canonical Encoding Rules.
1217
///
13-
/// X.680 defines not one but three sets of related encoding rules. All three
14-
/// follow the same basic ideas but implement them in slightly different
15-
/// ways.
18+
/// These rules always employ indefinite length encoding for constructed
19+
/// values and the shortest possible form for primitive values. There
20+
/// are additional restrictions for certain types.
21+
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
22+
pub struct Cer;
23+
24+
/// Distinguished Encoding Rules.
1625
///
17-
/// This type represents these rules. The [`decode`] method provides a way to
18-
/// decode a source using the specific decoding mode. You can also change
19-
/// the decoding mode later on through the `set_mode` methods of [`Primitive`]
20-
/// and [`Constructed`].
26+
/// These rules always employ definite length values and require the
27+
/// shortest possible encoding. Additional rules apply to some types.
28+
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
29+
pub struct Der;
30+
31+
/// One of the restricted rules CER or DER.
2132
///
22-
/// [`decode´]: #method.decode
23-
/// [`Primitive`]: decode/struct.Primitive.html
24-
/// [`Constructed`]: decode/struct.Constructed.html
25-
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
26-
pub enum Mode {
27-
/// Basic Encoding Rules.
28-
///
29-
/// These are the most flexible rules, allowing alternative encodings for
30-
/// some types as well as indefinite length values.
31-
#[default]
32-
Ber,
33+
/// Some restrictions to the basic rules are shared between CER and DER.
34+
/// This trait allows implementations to do both.
35+
pub trait Restricted { }
3336

34-
/// Canonical Encoding Rules.
35-
///
36-
/// These rules always employ indefinite length encoding for constructed
37-
/// values and the shortest possible form for primitive values. There
38-
/// are additional restrictions for certain types.
39-
Cer,
37+
impl Restricted for Cer { }
38+
impl Restricted for Der { }
4039

41-
/// Distinguished Encoding Rules.
42-
///
43-
/// These rules always employ definite length values and require the
44-
/// shortest possible encoding. Additional rules apply to some types.
45-
Der,
46-
}
40+
/// One of the modes.
41+
pub trait Mode {
42+
/// Is this mode CER or DER?
43+
const IS_RESTRICTED: bool;
4744

48-
impl Mode {
49-
/// Decode a source using a specific mode.
50-
///
51-
/// The method will attempt to decode `source` using the rules represented
52-
/// by this value. The closure `op` will be given the content of the
53-
/// source as a sequence of values. The closure does not need to process
54-
/// all values in the source.
55-
pub fn decode<S, F, T>(
56-
self, source: S, op: F,
57-
) -> Result<T, DecodeError<<S::Source as decode::Source>::Error>>
58-
where
59-
S: decode::IntoSource,
60-
F: FnOnce(
61-
&mut decode::Constructed<S::Source>
62-
) -> Result<T, DecodeError<<S::Source as decode::Source>::Error>>,
63-
{
64-
decode::Constructed::decode(source, self, op)
65-
}
45+
/// Does this mode allow definite-length constructed values?
46+
const ALLOW_DEFINITE_CONSTRUCTED: bool;
6647

67-
/// Returns whether the mode is `Mode::Ber`.
68-
pub fn is_ber(self) -> bool {
69-
matches!(self, Mode::Ber)
70-
}
48+
/// Does this mode allow indefinite length constructed values?
49+
const ALLOW_INDEFINITE_CONSTRUCTED: bool;
50+
}
51+
52+
impl Mode for Ber {
53+
const IS_RESTRICTED: bool = false;
54+
const ALLOW_DEFINITE_CONSTRUCTED: bool = true;
55+
const ALLOW_INDEFINITE_CONSTRUCTED: bool = true;
56+
}
7157

72-
/// Returns whether the mode is `Mode::Cer`.
73-
pub fn is_cer(self) -> bool {
74-
matches!(self, Mode::Cer)
75-
}
58+
impl Mode for Cer {
59+
const IS_RESTRICTED: bool = true;
60+
const ALLOW_DEFINITE_CONSTRUCTED: bool = false;
61+
const ALLOW_INDEFINITE_CONSTRUCTED: bool = true;
62+
}
7663

77-
/// Returns whether the mode is `Mode::Der`.
78-
pub fn is_der(self) -> bool {
79-
matches!(self, Mode::Der)
80-
}
64+
impl Mode for Der {
65+
const IS_RESTRICTED: bool = true;
66+
const ALLOW_DEFINITE_CONSTRUCTED: bool = true;
67+
const ALLOW_INDEFINITE_CONSTRUCTED: bool = false;
8168
}
8269

‎src/tag.rs

Lines changed: 407 additions & 417 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.