diff options
Diffstat (limited to 'vendor/const-oid/src/db.rs')
-rw-r--r-- | vendor/const-oid/src/db.rs | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/vendor/const-oid/src/db.rs b/vendor/const-oid/src/db.rs new file mode 100644 index 0000000..e4b7a47 --- /dev/null +++ b/vendor/const-oid/src/db.rs @@ -0,0 +1,164 @@ +//! OID Names Database +//! +//! The contents of this database are generated from the official IANA +//! [Object Identifier Descriptors] Registry CSV file and from [RFC 5280]. +//! If we are missing values you care about, please contribute a patch to +//! `oiddbgen` (a subcrate in the source code) to generate the values from +//! the relevant standard. +//! +//! [RFC 5280]: https://datatracker.ietf.org/doc/html/rfc5280 +//! [Object Identifier Descriptors]: https://www.iana.org/assignments/ldap-parameters/ldap-parameters.xhtml#ldap-parameters-3 + +#![allow(clippy::integer_arithmetic, missing_docs)] + +mod gen; + +pub use gen::*; + +use crate::{Error, ObjectIdentifier}; + +/// A const implementation of byte equals. +const fn eq(lhs: &[u8], rhs: &[u8]) -> bool { + if lhs.len() != rhs.len() { + return false; + } + + let mut i = 0usize; + while i < lhs.len() { + if lhs[i] != rhs[i] { + return false; + } + + i += 1; + } + + true +} + +/// A const implementation of case-insensitive ASCII equals. +const fn eq_case(lhs: &[u8], rhs: &[u8]) -> bool { + if lhs.len() != rhs.len() { + return false; + } + + let mut i = 0usize; + while i < lhs.len() { + if !lhs[i].eq_ignore_ascii_case(&rhs[i]) { + return false; + } + + i += 1; + } + + true +} + +/// A query interface for OIDs/Names. +#[derive(Copy, Clone)] +pub struct Database<'a>(&'a [(&'a ObjectIdentifier, &'a str)]); + +impl<'a> Database<'a> { + /// Looks up a name for an OID. + /// + /// Errors if the input is not a valid OID. + /// Returns the input if no name is found. + pub fn resolve<'b>(&self, oid: &'b str) -> Result<&'b str, Error> + where + 'a: 'b, + { + Ok(self.by_oid(&oid.parse()?).unwrap_or(oid)) + } + + /// Finds a named oid by its associated OID. + pub const fn by_oid(&self, oid: &ObjectIdentifier) -> Option<&'a str> { + let mut i = 0; + + while i < self.0.len() { + let lhs = self.0[i].0; + if lhs.length == oid.length && eq(&lhs.bytes, &oid.bytes) { + return Some(self.0[i].1); + } + + i += 1; + } + + None + } + + /// Finds a named oid by its associated name. + pub const fn by_name(&self, name: &str) -> Option<&'a ObjectIdentifier> { + let mut i = 0; + + while i < self.0.len() { + let lhs = self.0[i].1; + if eq_case(lhs.as_bytes(), name.as_bytes()) { + return Some(self.0[i].0); + } + + i += 1; + } + + None + } + + /// Return the list of matched name for the OID. + pub const fn find_names_for_oid(&self, oid: ObjectIdentifier) -> Names<'a> { + Names { + database: *self, + oid, + position: 0, + } + } +} + +/// Iterator returning the multiple names that may be associated with an OID. +pub struct Names<'a> { + database: Database<'a>, + oid: ObjectIdentifier, + position: usize, +} + +impl<'a> Iterator for Names<'a> { + type Item = &'a str; + + fn next(&mut self) -> Option<&'a str> { + let mut i = self.position; + + while i < self.database.0.len() { + let lhs = self.database.0[i].0; + + if lhs.as_bytes().eq(self.oid.as_bytes()) { + self.position = i + 1; + return Some(self.database.0[i].1); + } + + i += 1; + } + + None + } +} + +#[cfg(test)] +mod tests { + use crate::ObjectIdentifier; + + use super::rfc4519::CN; + + #[test] + fn by_oid() { + let cn = super::DB.by_oid(&CN).expect("cn not found"); + assert_eq!("cn", cn); + + let none = ObjectIdentifier::new_unwrap("0.1.2.3.4.5.6.7.8.9"); + assert_eq!(None, super::DB.by_oid(&none)); + } + + #[test] + fn by_name() { + let cn = super::DB.by_name("CN").expect("cn not found"); + assert_eq!(&CN, cn); + + assert_eq!(None, super::DB.by_name("purplePeopleEater")); + } +} |