1#![allow(clippy::arithmetic_side_effects, missing_docs)]
13
14mod generated;
15
16pub use generated::*;
17
18use crate::{Error, ObjectIdentifier};
19
20const fn eq_case(lhs: &[u8], rhs: &[u8]) -> bool {
22 if lhs.len() != rhs.len() {
23 return false;
24 }
25
26 let mut i = 0usize;
27 while i < lhs.len() {
28 if !lhs[i].eq_ignore_ascii_case(&rhs[i]) {
29 return false;
30 }
31
32 i += 1;
33 }
34
35 true
36}
37
38#[derive(Copy, Clone)]
40pub struct Database<'a>(&'a [(&'a ObjectIdentifier, &'a str)]);
41
42impl<'a> Database<'a> {
43 pub fn resolve<'b>(&self, oid: &'b str) -> Result<&'b str, Error>
48 where
49 'a: 'b,
50 {
51 Ok(self.by_oid(&oid.parse()?).unwrap_or(oid))
52 }
53
54 pub const fn by_oid(&self, oid: &ObjectIdentifier) -> Option<&'a str> {
56 let mut i = 0;
57
58 while i < self.0.len() {
59 let lhs = self.0[i].0;
60
61 if lhs.ber.eq(&oid.ber) {
62 return Some(self.0[i].1);
63 }
64
65 i += 1;
66 }
67
68 None
69 }
70
71 pub const fn by_name(&self, name: &str) -> Option<&'a ObjectIdentifier> {
73 let mut i = 0;
74
75 while i < self.0.len() {
76 let lhs = self.0[i].1;
77 if eq_case(lhs.as_bytes(), name.as_bytes()) {
78 return Some(self.0[i].0);
79 }
80
81 i += 1;
82 }
83
84 None
85 }
86
87 pub const fn find_names_for_oid(&self, oid: ObjectIdentifier) -> Names<'a> {
89 Names {
90 database: *self,
91 oid,
92 position: 0,
93 }
94 }
95}
96
97pub struct Names<'a> {
99 database: Database<'a>,
100 oid: ObjectIdentifier,
101 position: usize,
102}
103
104impl<'a> Iterator for Names<'a> {
105 type Item = &'a str;
106
107 fn next(&mut self) -> Option<&'a str> {
108 let mut i = self.position;
109
110 while i < self.database.0.len() {
111 let lhs = self.database.0[i].0;
112
113 if lhs.ber.eq(&self.oid.ber) {
114 self.position = i + 1;
115 return Some(self.database.0[i].1);
116 }
117
118 i += 1;
119 }
120
121 None
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use crate::ObjectIdentifier;
128
129 use super::rfc4519::CN;
130
131 #[test]
132 fn by_oid() {
133 let cn = super::DB.by_oid(&CN).expect("cn not found");
134 assert_eq!("cn", cn);
135
136 let none = ObjectIdentifier::new_unwrap("0.1.2.3.4.5.6.7.8.9");
137 assert_eq!(None, super::DB.by_oid(&none));
138 }
139
140 #[test]
141 fn by_name() {
142 let cn = super::DB.by_name("CN").expect("cn not found");
143 assert_eq!(&CN, cn);
144
145 assert_eq!(None, super::DB.by_name("purplePeopleEater"));
146 }
147}