1//! Arcs are integer values which exist within an OID's hierarchy.
23use crate::{Error, ObjectIdentifier, Result};
4use core::mem;
56/// Type used to represent an "arc" (i.e. integer identifier value).
7pub type Arc = u32;
89/// Maximum value of the first arc in an OID.
10pub(crate) const ARC_MAX_FIRST: Arc = 2;
1112/// Maximum value of the second arc in an OID.
13pub(crate) const ARC_MAX_SECOND: Arc = 39;
1415/// Maximum number of bytes supported in an arc.
16pub(crate) const ARC_MAX_BYTES: usize = mem::size_of::<Arc>();
1718/// Maximum value of the last byte in an arc.
19pub(crate) const ARC_MAX_LAST_OCTET: u8 = 0b11110000; // Max bytes of leading 1-bits
2021/// [`Iterator`] over arcs (a.k.a. nodes) in an [`ObjectIdentifier`].
22///
23/// This iterates over all arcs in an OID, including the root.
24pub struct Arcs<'a> {
25/// OID we're iterating over
26oid: &'a ObjectIdentifier,
2728/// Current position within the serialized DER bytes of this OID
29cursor: Option<usize>,
30}
3132impl<'a> Arcs<'a> {
33/// Create a new iterator over the arcs of this OID
34pub(crate) fn new(oid: &'a ObjectIdentifier) -> Self {
35Self { oid, cursor: None }
36 }
37}
3839impl<'a> Iterator for Arcs<'a> {
40type Item = Arc;
4142fn next(&mut self) -> Option<Arc> {
43match self.cursor {
44// Indicates we're on the root OID
45None => {
46let root = RootArcs(self.oid.as_bytes()[0]);
47self.cursor = Some(0);
48Some(root.first_arc())
49 }
50Some(0) => {
51let root = RootArcs(self.oid.as_bytes()[0]);
52self.cursor = Some(1);
53Some(root.second_arc())
54 }
55Some(offset) => {
56let mut result = 0;
57let mut arc_bytes = 0;
5859// TODO(tarcieri): consolidate this with `ObjectIdentifier::from_bytes`?
60loop {
61match self.oid.as_bytes().get(offset + arc_bytes).cloned() {
62Some(byte) => {
63 arc_bytes += 1;
64debug_assert!(
65 arc_bytes <= ARC_MAX_BYTES || byte & ARC_MAX_LAST_OCTET == 0,
66"OID arc overflowed"
67);
68 result = result << 7 | (byte & 0b1111111) as Arc;
6970if byte & 0b10000000 == 0 {
71self.cursor = Some(offset + arc_bytes);
72return Some(result);
73 }
74 }
75None => {
76debug_assert_eq!(arc_bytes, 0, "truncated OID");
77return None;
78 }
79 }
80 }
81 }
82 }
83 }
84}
8586/// Byte containing the first and second arcs of an OID.
87///
88/// This is represented this way in order to reduce the overall size of the
89/// [`ObjectIdentifier`] struct.
90#[derive(Copy, Clone, Debug, Eq, PartialEq)]
91pub(crate) struct RootArcs(u8);
9293impl RootArcs {
94/// Create [`RootArcs`] from the first and second arc values represented
95 /// as `Arc` integers.
96pub(crate) fn new(first_arc: Arc, second_arc: Arc) -> Result<Self> {
97if first_arc > ARC_MAX_FIRST || second_arc > ARC_MAX_SECOND {
98return Err(Error);
99 }
100101let byte = (first_arc * (ARC_MAX_SECOND + 1)) as u8 + second_arc as u8;
102Ok(Self(byte))
103 }
104105/// Get the value of the first arc
106pub(crate) fn first_arc(self) -> Arc {
107self.0 as Arc / (ARC_MAX_SECOND + 1)
108 }
109110/// Get the value of the second arc
111pub(crate) fn second_arc(self) -> Arc {
112self.0 as Arc % (ARC_MAX_SECOND + 1)
113 }
114}
115116impl TryFrom<u8> for RootArcs {
117type Error = Error;
118119fn try_from(octet: u8) -> Result<Self> {
120let first = octet as Arc / (ARC_MAX_SECOND + 1);
121let second = octet as Arc % (ARC_MAX_SECOND + 1);
122let result = Self::new(first, second)?;
123debug_assert_eq!(octet, result.0);
124Ok(result)
125 }
126}
127128impl From<RootArcs> for u8 {
129fn from(root_arcs: RootArcs) -> u8 {
130 root_arcs.0
131}
132}