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/media/6ee8e381/logo.svg",
6 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
7)]
8#![forbid(unsafe_code)]
9#![warn(
10 clippy::integer_arithmetic,
11 clippy::panic,
12 clippy::panic_in_result_fn,
13 clippy::unwrap_used,
14 missing_docs,
15 rust_2018_idioms,
16 unused_lifetimes,
17 unused_qualifications
18)]
19
20#[cfg(feature = "std")]
21extern crate std;
22
23#[macro_use]
24mod checked;
25
26mod arcs;
27mod encoder;
28mod error;
29mod parser;
30
31#[cfg(feature = "db")]
32#[cfg_attr(docsrs, doc(cfg(feature = "db")))]
33pub mod db;
34
35pub use crate::{
36 arcs::{Arc, Arcs},
37 error::{Error, Result},
38};
39
40use crate::encoder::Encoder;
41use core::{fmt, str::FromStr};
42
43pub trait AssociatedOid {
45 const OID: ObjectIdentifier;
47}
48
49pub trait DynAssociatedOid {
55 fn oid(&self) -> ObjectIdentifier;
57}
58
59impl<T: AssociatedOid> DynAssociatedOid for T {
60 fn oid(&self) -> ObjectIdentifier {
61 T::OID
62 }
63}
64
65#[derive(Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
81pub struct ObjectIdentifier {
82 length: u8,
84
85 bytes: [u8; Self::MAX_SIZE],
87}
88
89#[allow(clippy::len_without_is_empty)]
90impl ObjectIdentifier {
91 pub const MAX_SIZE: usize = 39; pub const fn new_unwrap(s: &str) -> Self {
113 match Self::new(s) {
114 Ok(oid) => oid,
115 Err(err) => err.panic(),
116 }
117 }
118
119 pub const fn new(s: &str) -> Result<Self> {
121 match parser::Parser::parse(s) {
123 Ok(parser) => parser.finish(),
124 Err(err) => Err(err),
125 }
126 }
127
128 pub fn from_arcs(arcs: impl IntoIterator<Item = Arc>) -> Result<Self> {
130 let mut encoder = Encoder::new();
131
132 for arc in arcs {
133 encoder = encoder.arc(arc)?;
134 }
135
136 encoder.finish()
137 }
138
139 pub fn from_bytes(ber_bytes: &[u8]) -> Result<Self> {
141 let len = ber_bytes.len();
142
143 match len {
144 0 => return Err(Error::Empty),
145 3..=Self::MAX_SIZE => (),
146 _ => return Err(Error::NotEnoughArcs),
147 }
148 let mut bytes = [0u8; Self::MAX_SIZE];
149 bytes[..len].copy_from_slice(ber_bytes);
150
151 let oid = Self {
152 bytes,
153 length: len as u8,
154 };
155
156 let mut arcs = oid.arcs();
158 while arcs.try_next()?.is_some() {}
159
160 Ok(oid)
161 }
162
163 pub fn as_bytes(&self) -> &[u8] {
168 &self.bytes[..self.length as usize]
169 }
170
171 pub fn arc(&self, index: usize) -> Option<Arc> {
173 self.arcs().nth(index)
174 }
175
176 pub fn arcs(&self) -> Arcs<'_> {
180 Arcs::new(self)
181 }
182
183 pub fn len(&self) -> usize {
185 self.arcs().count()
186 }
187
188 pub fn parent(&self) -> Option<Self> {
190 let num_arcs = self.len().checked_sub(1)?;
191 Self::from_arcs(self.arcs().take(num_arcs)).ok()
192 }
193
194 pub const fn push_arc(self, arc: Arc) -> Result<Self> {
196 match Encoder::extend(self).arc(arc) {
198 Ok(encoder) => encoder.finish(),
199 Err(err) => Err(err),
200 }
201 }
202}
203
204impl AsRef<[u8]> for ObjectIdentifier {
205 fn as_ref(&self) -> &[u8] {
206 self.as_bytes()
207 }
208}
209
210impl FromStr for ObjectIdentifier {
211 type Err = Error;
212
213 fn from_str(string: &str) -> Result<Self> {
214 Self::new(string)
215 }
216}
217
218impl TryFrom<&[u8]> for ObjectIdentifier {
219 type Error = Error;
220
221 fn try_from(ber_bytes: &[u8]) -> Result<Self> {
222 Self::from_bytes(ber_bytes)
223 }
224}
225
226impl From<&ObjectIdentifier> for ObjectIdentifier {
227 fn from(oid: &ObjectIdentifier) -> ObjectIdentifier {
228 *oid
229 }
230}
231
232impl fmt::Debug for ObjectIdentifier {
233 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
234 write!(f, "ObjectIdentifier({})", self)
235 }
236}
237
238impl fmt::Display for ObjectIdentifier {
239 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240 let len = self.arcs().count();
241
242 for (i, arc) in self.arcs().enumerate() {
243 write!(f, "{}", arc)?;
244
245 if let Some(j) = i.checked_add(1) {
246 if j < len {
247 write!(f, ".")?;
248 }
249 }
250 }
251
252 Ok(())
253 }
254}
255
256#[cfg(feature = "arbitrary")]
259impl<'a> arbitrary::Arbitrary<'a> for ObjectIdentifier {
260 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
261 let first = u.int_in_range(0..=arcs::ARC_MAX_FIRST)?;
262 let second = u.int_in_range(0..=arcs::ARC_MAX_SECOND)?;
263 let third = u.arbitrary()?;
264
265 let mut oid = Self::from_arcs([first, second, third])
266 .map_err(|_| arbitrary::Error::IncorrectFormat)?;
267
268 for arc in u.arbitrary_iter()? {
269 oid = oid
270 .push_arc(arc?)
271 .map_err(|_| arbitrary::Error::IncorrectFormat)?;
272 }
273
274 Ok(oid)
275 }
276
277 fn size_hint(depth: usize) -> (usize, Option<usize>) {
278 (Arc::size_hint(depth).0.saturating_mul(3), None)
279 }
280}