yasna/models/
oid.rs

1// Copyright 2016 Masaki Hara
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use core::fmt::{self, Display};
10#[cfg(feature = "std")]
11use std::error::Error;
12use alloc::str::FromStr;
13use alloc::vec::Vec;
14
15/// A type that represents object identifiers.
16///
17/// This is actually a thin wrapper of `Vec<u64>`.
18///
19/// # Examples
20///
21/// ```
22/// use yasna::models::ObjectIdentifier;
23/// let sha384WithRSAEncryption = ObjectIdentifier::from_slice(&
24///     [1, 2, 840, 113549, 1, 1, 12]);
25/// println!("{}", sha384WithRSAEncryption);
26/// ```
27#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
28pub struct ObjectIdentifier {
29    components: Vec<u64>,
30}
31
32impl ObjectIdentifier {
33    /// Constructs a new `ObjectIdentifier` from `Vec<u64>`.
34    ///
35    /// # Examples
36    ///
37    /// ```
38    /// use yasna::models::ObjectIdentifier;
39    /// let pkcs1 = ObjectIdentifier::new(
40    ///     [1, 2, 840, 113549, 1, 1].to_vec());
41    /// println!("{}", pkcs1);
42    /// ```
43    pub fn new(components: Vec<u64>) -> Self {
44        return ObjectIdentifier {
45            components,
46        };
47    }
48
49    /// Constructs a new `ObjectIdentifier` from `&[u64]`.
50    ///
51    /// # Examples
52    ///
53    /// ```
54    /// use yasna::models::ObjectIdentifier;
55    /// let pkcs1 = ObjectIdentifier::from_slice(&
56    ///     [1, 2, 840, 113549, 1, 1]);
57    /// println!("{}", pkcs1);
58    /// ```
59    pub fn from_slice(components: &[u64]) -> Self {
60        return ObjectIdentifier {
61            components: components.to_vec(),
62        };
63    }
64
65    /// Borrows its internal vector of components.
66    ///
67    /// # Examples
68    ///
69    /// ```
70    /// use yasna::models::ObjectIdentifier;
71    /// let pkcs1 = ObjectIdentifier::from_slice(&
72    ///     [1, 2, 840, 113549, 1, 1]);
73    /// let components : &Vec<u64> = pkcs1.components();
74    /// ```
75    pub fn components(&self) -> &Vec<u64> {
76        &self.components
77    }
78
79    /// Mutably borrows its internal vector of components.
80    ///
81    /// # Examples
82    ///
83    /// ```
84    /// use yasna::models::ObjectIdentifier;
85    /// let mut pkcs1 = ObjectIdentifier::from_slice(&
86    ///     [1, 2, 840, 113549, 1, 1]);
87    /// let components : &mut Vec<u64> = pkcs1.components_mut();
88    /// ```
89    pub fn components_mut(&mut self) -> &mut Vec<u64> {
90        &mut self.components
91    }
92
93    /// Extracts its internal vector of components.
94    ///
95    /// # Examples
96    ///
97    /// ```
98    /// use yasna::models::ObjectIdentifier;
99    /// let pkcs1 = ObjectIdentifier::from_slice(&
100    ///     [1, 2, 840, 113549, 1, 1]);
101    /// let mut components : Vec<u64> = pkcs1.into_components();
102    /// ```
103    pub fn into_components(self) -> Vec<u64> {
104        self.components
105    }
106}
107
108impl Display for ObjectIdentifier {
109    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
110        let mut fst = true;
111        for &component in &self.components {
112            if fst {
113                write!(f, "{}", component)?;
114            } else {
115                write!(f, ".{}", component)?;
116            }
117            fst = false;
118        }
119        return Ok(());
120    }
121}
122
123#[derive(Debug, Clone)]
124/// An error indicating failure to parse an Object identifier
125pub struct ParseOidError(());
126
127#[cfg(feature = "std")]
128impl Error for ParseOidError {}
129
130impl Display for ParseOidError {
131    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
132        f.write_str("Failed to parse OID")
133    }
134}
135
136
137impl FromStr for ObjectIdentifier {
138    type Err = ParseOidError;
139
140    fn from_str(s: &str) -> Result<Self, Self::Err> {
141        s.split(".")
142            .map(|s| s.parse().map_err(|_| ParseOidError(()) ))
143            .collect::<Result<_, _>>()
144            .map(ObjectIdentifier::new)
145    }
146}
147
148impl AsRef<[u64]> for ObjectIdentifier {
149    fn as_ref(&self) -> &[u64] {
150        &self.components
151    }
152}
153
154impl From<Vec<u64>> for ObjectIdentifier {
155    fn from(components: Vec<u64>) -> ObjectIdentifier {
156        Self::new(components)
157    }
158}
159
160#[test]
161fn test_display_oid() {
162    use alloc::format;
163    let pkcs1 = ObjectIdentifier::from_slice(&[1, 2, 840, 113549, 1, 1]);
164    assert_eq!(format!("{}", pkcs1), "1.2.840.113549.1.1");
165}
166
167#[test]
168fn parse_oid() {
169    assert_eq!("1.2.840.113549.1.1".parse::<ObjectIdentifier>().unwrap().components(), &[1, 2, 840, 113549, 1, 1]);
170    "1.2.840.113549.1.1.".parse::<ObjectIdentifier>().unwrap_err();
171    "1.2.840.113549.1.1x".parse::<ObjectIdentifier>().unwrap_err();
172    "".parse::<ObjectIdentifier>().unwrap_err();
173}