Coverage Report

Created: 2026-01-16 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/oid-registry-0.6.1/src/lib.rs
Line
Count
Source
1
//! [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE-MIT)
2
//! [![Apache License 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE-APACHE)
3
//! [![docs.rs](https://docs.rs/oid-registry/badge.svg)](https://docs.rs/oid-registry)
4
//! [![crates.io](https://img.shields.io/crates/v/oid-registry.svg)](https://crates.io/crates/oid-registry)
5
//! [![Github CI](https://github.com/rusticata/oid-registry/workflows/Continuous%20integration/badge.svg)](https://github.com/rusticata/oid-registry/actions)
6
//! [![Minimum rustc version](https://img.shields.io/badge/rustc-1.53.0+-lightgray.svg)](#rust-version-requirements)
7
//! # OID Registry
8
//!
9
//! This crate is a helper crate, containing a database of OID objects. These objects are intended
10
//! for use when manipulating ASN.1 grammars and BER/DER encodings, for example.
11
//!
12
//! This crate provides only a simple registry (similar to a `HashMap`) by default. This object can
13
//! be used to get names and descriptions from OID.
14
//!
15
//! This crate provides default lists of known OIDs, that can be selected using the build features.
16
//! By default, the registry has no feature enabled, to avoid embedding a huge database in crates.
17
//!
18
//! It also declares constants for most of these OIDs.
19
//!
20
//! ```rust
21
//! use oid_registry::OidRegistry;
22
//!
23
//! let mut registry = OidRegistry::default()
24
//! # ;
25
//! # #[cfg(feature = "crypto")] {
26
//! #     registry = registry
27
//!     .with_crypto() // only if the 'crypto' feature is enabled
28
//! # }
29
//! ;
30
//!
31
//! let e = registry.get(&oid_registry::OID_PKCS1_SHA256WITHRSA);
32
//! if let Some(entry) = e {
33
//!     // get sn: sha256WithRSAEncryption
34
//!     println!("sn: {}", entry.sn());
35
//!     // get description: SHA256 with RSA encryption
36
//!     println!("description: {}", entry.description());
37
//! }
38
//!
39
//! ```
40
//!
41
//! ## Extending the registry
42
//!
43
//! These provided lists are often incomplete, or may lack some specific OIDs.
44
//! This is why the registry allows adding new entries after construction:
45
//!
46
//! ```rust
47
//! use asn1_rs::oid;
48
//! use oid_registry::{OidEntry, OidRegistry};
49
//!
50
//! let mut registry = OidRegistry::default();
51
//!
52
//! // entries can be added by creating an OidEntry object:
53
//! let entry = OidEntry::new("shortName", "description");
54
//! registry.insert(oid!(1.2.3.4), entry);
55
//!
56
//! // when using static strings, a tuple can also be used directly for the entry:
57
//! registry.insert(oid!(1.2.3.5), ("shortName", "A description"));
58
//!
59
//! ```
60
//!
61
//! ## Contributing OIDs
62
//!
63
//! All OID values, constants, and features are derived from files in the `assets` directory in the
64
//! build script (see `build.rs`).
65
//! See `load_file` for documentation of the file format.
66
67
#![deny(missing_docs, unstable_features, unused_import_braces, unused_qualifications, unreachable_pub)]
68
#![forbid(unsafe_code)]
69
#![warn(
70
      /* missing_docs,
71
      rust_2018_idioms,*/
72
      missing_debug_implementations,
73
  )]
74
// pragmas for doc
75
// #![deny(intra_doc_link_resolution_failure)]
76
#![cfg_attr(docsrs, feature(doc_cfg))]
77
78
pub use asn1_rs;
79
pub use asn1_rs::Oid;
80
81
use asn1_rs::oid;
82
use std::borrow::Cow;
83
use std::collections::HashMap;
84
use std::convert::From;
85
86
mod load;
87
88
pub use load::*;
89
90
/// An entry stored in the OID registry
91
#[derive(Debug)]
92
pub struct OidEntry {
93
    // Short name
94
    sn: Cow<'static, str>,
95
    description: Cow<'static, str>,
96
}
97
98
impl OidEntry {
99
    /// Create a new entry
100
296
    pub fn new<S, T>(sn: S, description: T) -> OidEntry
101
296
    where
102
296
        S: Into<Cow<'static, str>>,
103
296
        T: Into<Cow<'static, str>>,
104
    {
105
296
        let sn = sn.into();
106
296
        let description = description.into();
107
296
        OidEntry { sn, description }
108
296
    }
<oid_registry::OidEntry>::new::<&str, &str>
Line
Count
Source
100
2
    pub fn new<S, T>(sn: S, description: T) -> OidEntry
101
2
    where
102
2
        S: Into<Cow<'static, str>>,
103
2
        T: Into<Cow<'static, str>>,
104
    {
105
2
        let sn = sn.into();
106
2
        let description = description.into();
107
2
        OidEntry { sn, description }
108
2
    }
<oid_registry::OidEntry>::new::<&str, &str>
Line
Count
Source
100
294
    pub fn new<S, T>(sn: S, description: T) -> OidEntry
101
294
    where
102
294
        S: Into<Cow<'static, str>>,
103
294
        T: Into<Cow<'static, str>>,
104
    {
105
294
        let sn = sn.into();
106
294
        let description = description.into();
107
294
        OidEntry { sn, description }
108
294
    }
109
110
    /// Get the short name for this entry
111
    #[inline]
112
12
    pub fn sn(&self) -> &str {
113
12
        &self.sn
114
12
    }
115
116
    /// Get the description for this entry
117
    #[inline]
118
0
    pub fn description(&self) -> &str {
119
0
        &self.description
120
0
    }
121
}
122
123
impl From<(&'static str, &'static str)> for OidEntry {
124
0
    fn from(t: (&'static str, &'static str)) -> Self {
125
0
        Self::new(t.0, t.1)
126
0
    }
127
}
128
129
/// Registry of known OIDs
130
///
131
/// Use `OidRegistry::default()` to create an empty registry. If the corresponding features have
132
/// been selected, the `with_xxx()` methods can be used to add sets of known objets to the
133
/// database.
134
///
135
/// # Example
136
///
137
/// ```rust
138
/// use asn1_rs::{oid, Oid};
139
/// use oid_registry::{OidEntry, OidRegistry};
140
///
141
/// let mut registry = OidRegistry::default()
142
/// # ;
143
/// # #[cfg(feature = "crypto")] {
144
/// #     registry = registry
145
///     .with_crypto() // only if the 'crypto' feature is enabled
146
/// # }
147
/// ;
148
///
149
/// // entries can be added by creating an OidEntry object:
150
/// let entry = OidEntry::new("shortName", "description");
151
/// registry.insert(oid!(1.2.3.4), entry);
152
///
153
/// // when using static strings, a tuple can also be used directly for the entry:
154
/// registry.insert(oid!(1.2.3.5), ("shortName", "A description"));
155
///
156
/// // To query an entry, use the `get` method:
157
/// const OID_1234: Oid<'static> = oid!(1.2.3.4);
158
/// let e = registry.get(&OID_1234);
159
/// assert!(e.is_some());
160
/// if let Some(e) = e {
161
///     assert_eq!(e.sn(), "shortName");
162
/// }
163
/// ```
164
#[derive(Debug, Default)]
165
pub struct OidRegistry<'a> {
166
    map: HashMap<Oid<'a>, OidEntry>,
167
}
168
169
impl<'a> OidRegistry<'a> {
170
    /// Insert a new entry
171
296
    pub fn insert<E>(&mut self, oid: Oid<'a>, entry: E) -> Option<OidEntry>
172
296
    where
173
296
        E: Into<OidEntry>,
174
    {
175
296
        self.map.insert(oid, entry.into())
176
296
    }
<oid_registry::OidRegistry>::insert::<oid_registry::OidEntry>
Line
Count
Source
171
2
    pub fn insert<E>(&mut self, oid: Oid<'a>, entry: E) -> Option<OidEntry>
172
2
    where
173
2
        E: Into<OidEntry>,
174
    {
175
2
        self.map.insert(oid, entry.into())
176
2
    }
<oid_registry::OidRegistry>::insert::<oid_registry::OidEntry>
Line
Count
Source
171
294
    pub fn insert<E>(&mut self, oid: Oid<'a>, entry: E) -> Option<OidEntry>
172
294
    where
173
294
        E: Into<OidEntry>,
174
    {
175
294
        self.map.insert(oid, entry.into())
176
294
    }
177
178
    /// Returns a reference to the registry entry, if found for this OID.
179
116
    pub fn get(&self, oid: &Oid<'a>) -> Option<&OidEntry> {
180
116
        self.map.get(oid)
181
116
    }
182
183
    /// Return an Iterator over references to the OID numbers (registry keys)
184
0
    pub fn keys(&self) -> impl Iterator<Item = &Oid<'a>> {
185
0
        self.map.keys()
186
0
    }
187
188
    /// Return an Iterator over references to the `OidEntry` values
189
0
    pub fn values(&self) -> impl Iterator<Item = &OidEntry> {
190
0
        self.map.values()
191
0
    }
192
193
    /// Return an Iterator over references to the `(Oid, OidEntry)` key/value pairs
194
0
    pub fn iter(&self) -> impl Iterator<Item = (&Oid<'a>, &OidEntry)> {
195
0
        self.map.iter()
196
0
    }
197
198
    /// Return the `(Oid, OidEntry)` key/value pairs, matching a short name
199
    ///
200
    /// The registry should not contain entries with same short name to avoid ambiguity, but it is
201
    /// not mandatory.
202
    ///
203
    /// This function returns an iterator over the key/value pairs. In most cases, it will have 0
204
    /// (not found) or 1 item, but can contain more if there are multiple definitions.
205
    ///
206
    /// ```rust
207
    /// # use oid_registry::OidRegistry;
208
    /// #
209
    /// # let registry = OidRegistry::default();
210
    /// // iterate all entries matching "shortName"
211
    /// for (oid, entry) in registry.iter_by_sn("shortName") {
212
    ///     // do something
213
    /// }
214
    ///
215
    /// // if you are *sure* that there is at most one entry:
216
    /// let opt_sn = registry.iter_by_sn("shortName").next();
217
    /// if let Some((oid, entry)) = opt_sn {
218
    ///     // do something
219
    /// }
220
    /// ```
221
0
    pub fn iter_by_sn<S: Into<String>>(&self, sn: S) -> impl Iterator<Item = (&Oid<'a>, &OidEntry)> {
222
0
        let s = sn.into();
223
0
        self.map.iter().filter(move |(_, entry)| entry.sn == s)
224
0
    }
225
226
    /// Populate registry with common crypto OIDs (encryption, hash algorithms)
227
    #[cfg(feature = "crypto")]
228
    #[cfg_attr(docsrs, doc(cfg(feature = "crypto")))]
229
2
    pub fn with_crypto(self) -> Self {
230
2
        self.with_pkcs1().with_x962().with_kdf().with_nist_algs()
231
2
    }
232
233
    /// Populate registry with all known crypto OIDs (encryption, hash algorithms, PKCS constants,
234
    /// etc.)
235
    #[cfg(feature = "crypto")]
236
    #[cfg_attr(docsrs, doc(cfg(feature = "crypto")))]
237
2
    pub fn with_all_crypto(self) -> Self {
238
2
        self.with_crypto().with_pkcs7().with_pkcs9().with_pkcs12()
239
2
    }
240
}
241
242
/// Format a OID to a `String`, using the provided registry to get the short name if present.
243
0
pub fn format_oid(oid: &Oid, registry: &OidRegistry) -> String {
244
0
    if let Some(entry) = registry.map.get(oid) {
245
0
        format!("{} ({})", entry.sn, oid)
246
    } else {
247
0
        format!("{}", oid)
248
    }
249
0
}
250
251
include!(concat!(env!("OUT_DIR"), "/oid_db.rs"));
252
253
#[rustfmt::skip::macros(oid)]
254
#[cfg(test)]
255
mod tests {
256
    use super::*;
257
258
    // This test is mostly a compile test, to ensure the API has not changed
259
    #[test]
260
    fn test_lifetimes() {
261
        fn add_entry(input: &str, oid: Oid<'static>, registry: &mut OidRegistry) {
262
            // test insertion of owned string
263
            let s = String::from(input);
264
            let entry = OidEntry::new("test", s);
265
            registry.insert(oid, entry);
266
        }
267
268
        let mut registry = OidRegistry::default();
269
        add_entry("a", oid!(1.2.3.4), &mut registry);
270
        add_entry("b", oid!(1.2.3.5), &mut registry);
271
272
        // test insertion of owned data
273
        let e = OidEntry::new("c", "test_c");
274
        registry.insert(oid!(1.2.4.1), e);
275
276
        registry.insert(oid!(1.2.5.1), ("a", "b"));
277
278
        let iter = registry.iter_by_sn("test");
279
        assert_eq!(iter.count(), 2);
280
281
        // dbg!(&registry);
282
    }
283
}