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}