1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc = include_str!("../README.md")]
4#![doc(
5 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
6 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
7 html_root_url = "https://docs.rs/const-oid/0.7.1"
8)]
9#![forbid(unsafe_code, clippy::unwrap_used)]
10#![warn(missing_docs, rust_2018_idioms)]
11
12#[cfg(feature = "std")]
13extern crate std;
14
15#[macro_use]
16mod macros;
17
18mod arcs;
19mod encoder;
20mod error;
21mod parser;
22
23pub use crate::{
24 arcs::{Arc, Arcs},
25 error::{Error, Result},
26};
27
28use crate::arcs::{RootArcs, ARC_MAX_BYTES, ARC_MAX_LAST_OCTET};
29use core::{fmt, str::FromStr};
30
31#[derive(Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
47pub struct ObjectIdentifier {
48 length: u8,
50
51 bytes: [u8; Self::MAX_SIZE],
53}
54
55#[allow(clippy::len_without_is_empty)]
56impl ObjectIdentifier {
57 pub const MAX_SIZE: usize = 39; pub const fn new(s: &str) -> Self {
83 parser::Parser::parse(s).finish()
84 }
85
86 pub fn from_arcs(arcs: &[Arc]) -> Result<Self> {
88 let mut bytes = [0u8; Self::MAX_SIZE];
89
90 bytes[0] = match *arcs {
91 [first, second, _, ..] => RootArcs::new(first, second)?.into(),
92 _ => return Err(Error),
93 };
94
95 let mut offset = 1;
96
97 for &arc in &arcs[2..] {
98 offset += encoder::write_base128(&mut bytes[offset..], arc)?;
99 }
100
101 Ok(Self {
102 bytes,
103 length: offset as u8,
104 })
105 }
106
107 pub fn from_bytes(ber_bytes: &[u8]) -> Result<Self> {
109 let len = ber_bytes.len();
110
111 if !(2..=Self::MAX_SIZE).contains(&len) {
112 return Err(Error);
113 }
114
115 ber_bytes
117 .get(0)
118 .cloned()
119 .ok_or(Error)
120 .and_then(RootArcs::try_from)?;
121
122 let mut arc_offset = 1;
124 let mut arc_bytes = 0;
125
126 while arc_offset < len {
128 match ber_bytes.get(arc_offset + arc_bytes).cloned() {
129 Some(byte) => {
130 if (arc_bytes == ARC_MAX_BYTES) && (byte & ARC_MAX_LAST_OCTET != 0) {
131 return Err(Error);
133 }
134
135 arc_bytes += 1;
136
137 if byte & 0b10000000 == 0 {
138 arc_offset += arc_bytes;
139 arc_bytes = 0;
140 }
141 }
142 None => return Err(Error), }
144 }
145
146 let mut bytes = [0u8; Self::MAX_SIZE];
147 bytes[..len].copy_from_slice(ber_bytes);
148
149 Ok(Self {
150 bytes,
151 length: len as u8,
152 })
153 }
154
155 pub fn as_bytes(&self) -> &[u8] {
160 &self.bytes[..self.length as usize]
161 }
162
163 pub fn arc(&self, index: usize) -> Option<Arc> {
165 self.arcs().nth(index)
166 }
167
168 pub fn arcs(&self) -> Arcs<'_> {
173 Arcs::new(self)
174 }
175}
176
177impl AsRef<[u8]> for ObjectIdentifier {
178 fn as_ref(&self) -> &[u8] {
179 self.as_bytes()
180 }
181}
182
183impl FromStr for ObjectIdentifier {
184 type Err = Error;
185
186 fn from_str(string: &str) -> Result<Self> {
187 let mut split = string.split('.');
188 let first_arc = split.next().and_then(|s| s.parse().ok()).ok_or(Error)?;
189 let second_arc = split.next().and_then(|s| s.parse().ok()).ok_or(Error)?;
190
191 let mut bytes = [0u8; Self::MAX_SIZE];
192 bytes[0] = RootArcs::new(first_arc, second_arc)?.into();
193
194 let mut offset = 1;
195
196 for s in split {
197 let arc = s.parse().map_err(|_| Error)?;
198 offset += encoder::write_base128(&mut bytes[offset..], arc)?;
199 }
200
201 if offset > 1 {
202 Ok(Self {
203 bytes,
204 length: offset as u8,
205 })
206 } else {
207 Err(Error)
209 }
210 }
211}
212
213impl TryFrom<&[u8]> for ObjectIdentifier {
214 type Error = Error;
215
216 fn try_from(ber_bytes: &[u8]) -> Result<Self> {
217 Self::from_bytes(ber_bytes)
218 }
219}
220
221impl From<&ObjectIdentifier> for ObjectIdentifier {
222 fn from(oid: &ObjectIdentifier) -> ObjectIdentifier {
223 *oid
224 }
225}
226
227impl fmt::Debug for ObjectIdentifier {
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 write!(f, "ObjectIdentifier({})", self)
230 }
231}
232
233impl fmt::Display for ObjectIdentifier {
234 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
235 let len = self.arcs().count();
236
237 for (i, arc) in self.arcs().enumerate() {
238 write!(f, "{}", arc)?;
239
240 if i < len - 1 {
241 write!(f, ".")?;
242 }
243 }
244
245 Ok(())
246 }
247}