Skip to content

Commit e914bac

Browse files
committed
const-oid: add ObjectIdentifierRef
Adds a `repr(transparent)` newtype for a `[u8]` which is guaranteed to contain a valid BER serialization of an OID. This is a similar approach to how `Path`/`PathBuf` or `OsStr`/`OsString` work (except with `ObjectIdentifier` being stack-allocated instead of heap allocated). An unsafe pointer cast is required to go from `&[u8]` to `&ObjectIdentifierRef`, so unfortunately this means the crate is no longer `forbid(unsafe_code)`, however it's been lowered to `deny(unsafe_code)` to ensure contributors think twice before adding more. `Borrow` and `Deref` impls have been added to the owned `ObjectIdentifier` type, allowing common functionality to be moved to `ObjectIdentifierRef`, allowing both types to exist while eliminating code duplication. A `PartialEq` impl allows them to be compared. The `db` module continues to use `ObjectIdentifier` for now, however hopefully this approach would allow #1212 to be reinstated and for `ObjectIdentifierRef`s to be used for the database eventually (i.e. revert the revert in #1299) NOTE: this PR also relaxes the previous requirement that an OID have at least three arcs. It is now allowed to only have two.
1 parent 12820eb commit e914bac

7 files changed

Lines changed: 253 additions & 110 deletions

File tree

const-oid/src/arcs.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ impl<'a> Arcs<'a> {
5858
match self.cursor {
5959
// Indicates we're on the root arc
6060
None => {
61-
let root = RootArcs::try_from(self.bytes[0])?;
61+
let root_byte = *self.bytes.first().ok_or(Error::Empty)?;
62+
let root = RootArcs::try_from(root_byte)?;
6263
self.cursor = Some(0);
6364
Ok(Some(root.first_arc()))
6465
}

const-oid/src/db.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ impl<'a> Database<'a> {
5858
while i < self.0.len() {
5959
let lhs = self.0[i].0;
6060

61-
if lhs.buffer.eq(&oid.buffer) {
61+
if lhs.ber.eq(&oid.ber) {
6262
return Some(self.0[i].1);
6363
}
6464

@@ -110,7 +110,7 @@ impl<'a> Iterator for Names<'a> {
110110
while i < self.database.0.len() {
111111
let lhs = self.database.0[i].0;
112112

113-
if lhs.buffer.eq(&self.oid.buffer) {
113+
if lhs.ber.eq(&self.oid.ber) {
114114
self.position = i + 1;
115115
return Some(self.database.0[i].1);
116116
}

const-oid/src/encoder.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,29 @@ use crate::{
55
Arc, Buffer, Error, ObjectIdentifier, Result,
66
};
77

8-
/// BER/DER encoder
8+
/// BER/DER encoder.
99
#[derive(Debug)]
1010
pub(crate) struct Encoder<const MAX_SIZE: usize> {
11-
/// Current state
11+
/// Current state.
1212
state: State,
1313

14-
/// Bytes of the OID being encoded in-progress
14+
/// Bytes of the OID being BER-encoded in-progress.
1515
bytes: [u8; MAX_SIZE],
1616

17-
/// Current position within the byte buffer
17+
/// Current position within the byte buffer.
1818
cursor: usize,
1919
}
2020

21-
/// Current state of the encoder
21+
/// Current state of the encoder.
2222
#[derive(Debug)]
2323
enum State {
24-
/// Initial state - no arcs yet encoded
24+
/// Initial state - no arcs yet encoded.
2525
Initial,
2626

27-
/// First arc parsed
27+
/// First arc parsed.
2828
FirstArc(Arc),
2929

30-
/// Encoding base 128 body of the OID
30+
/// Encoding base 128 body of the OID.
3131
Body,
3232
}
3333

@@ -45,8 +45,8 @@ impl<const MAX_SIZE: usize> Encoder<MAX_SIZE> {
4545
pub(crate) const fn extend(oid: ObjectIdentifier<MAX_SIZE>) -> Self {
4646
Self {
4747
state: State::Body,
48-
bytes: oid.buffer.bytes,
49-
cursor: oid.buffer.length as usize,
48+
bytes: oid.ber.bytes,
49+
cursor: oid.ber.length as usize,
5050
}
5151
}
5252

@@ -100,16 +100,16 @@ impl<const MAX_SIZE: usize> Encoder<MAX_SIZE> {
100100

101101
/// Finish encoding an OID.
102102
pub(crate) const fn finish(self) -> Result<ObjectIdentifier<MAX_SIZE>> {
103-
if self.cursor >= 2 {
104-
let bytes = Buffer {
105-
bytes: self.bytes,
106-
length: self.cursor as u8,
107-
};
108-
109-
Ok(ObjectIdentifier { buffer: bytes })
110-
} else {
111-
Err(Error::NotEnoughArcs)
103+
if self.cursor == 0 {
104+
return Err(Error::Empty);
112105
}
106+
107+
let ber = Buffer {
108+
bytes: self.bytes,
109+
length: self.cursor as u8,
110+
};
111+
112+
Ok(ObjectIdentifier { ber })
113113
}
114114

115115
/// Encode a single byte of a Base 128 value.

const-oid/src/error.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ pub enum Error {
3737
/// OID length is invalid (too short or too long).
3838
Length,
3939

40-
/// Minimum 3 arcs required.
41-
NotEnoughArcs,
42-
4340
/// Trailing `.` character at end of input.
4441
TrailingDot,
4542
}
@@ -56,7 +53,6 @@ impl Error {
5653
Error::DigitExpected { .. } => panic!("OID expected to start with digit"),
5754
Error::Empty => panic!("OID value is empty"),
5855
Error::Length => panic!("OID length invalid"),
59-
Error::NotEnoughArcs => panic!("OID requires minimum of 3 arcs"),
6056
Error::TrailingDot => panic!("OID ends with invalid trailing '.'"),
6157
}
6258
}
@@ -73,7 +69,6 @@ impl fmt::Display for Error {
7369
}
7470
Error::Empty => f.write_str("OID value is empty"),
7571
Error::Length => f.write_str("OID length invalid"),
76-
Error::NotEnoughArcs => f.write_str("OID requires minimum of 3 arcs"),
7772
Error::TrailingDot => f.write_str("OID ends with invalid trailing '.'"),
7873
}
7974
}

0 commit comments

Comments
 (0)