2021-11-26 02:25:48 +01:00
|
|
|
//! oid crate by <https://github.com/UnnecessaryEngineering/oid> turned into vendored module
|
2021-10-13 04:57:40 +02:00
|
|
|
//!
|
|
|
|
//! [Object Identifiers] are a standard of the [ITU] used to reference objects, things, and
|
|
|
|
//! concepts in a globally unique way. This crate provides for data structures and methods
|
|
|
|
//! to build, parse, and format OIDs.
|
|
|
|
//!
|
|
|
|
//!
|
|
|
|
//! ## Parsing OID String Representation
|
2021-10-18 10:39:31 +02:00
|
|
|
//! ```ignore
|
|
|
|
//! use crate::oid::prelude::*;
|
2021-10-13 04:57:40 +02:00
|
|
|
//!
|
|
|
|
//! fn main() -> Result<(), ObjectIdentifierError> {
|
|
|
|
//! let oid = ObjectIdentifier::try_from("0.1.2.3")?;
|
|
|
|
//! Ok(())
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! ## Parsing OID Binary Representation
|
2021-10-18 10:39:31 +02:00
|
|
|
//! ```ignore
|
|
|
|
//! use prelude::*;
|
2021-10-13 04:57:40 +02:00
|
|
|
//!
|
|
|
|
//! fn main() -> Result<(), ObjectIdentifierError> {
|
|
|
|
//! let oid = ObjectIdentifier::try_from(vec![0x00, 0x01, 0x02, 0x03])?;
|
|
|
|
//! Ok(())
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! ## Encoding OID as String Representation
|
2021-10-18 10:39:31 +02:00
|
|
|
//! ```ignore
|
|
|
|
//! use prelude::*;
|
2021-10-13 04:57:40 +02:00
|
|
|
//!
|
|
|
|
//! fn main() -> Result<(), ObjectIdentifierError> {
|
|
|
|
//! let oid = ObjectIdentifier::try_from("0.1.2.3")?;
|
|
|
|
//! let oid: String = oid.into();
|
|
|
|
//! assert_eq!(oid, "0.1.2.3");
|
|
|
|
//! Ok(())
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! ## Encoding OID as Binary Representation
|
2021-10-18 10:39:31 +02:00
|
|
|
//! ```ignore
|
2021-10-13 04:57:40 +02:00
|
|
|
//! use oid::prelude::*;
|
|
|
|
//!
|
|
|
|
//! fn main() -> Result<(), ObjectIdentifierError> {
|
|
|
|
//! let oid = ObjectIdentifier::try_from(vec![0x00, 0x01, 0x02, 0x03])?;
|
|
|
|
//! let oid: Vec<u8> = oid.into();
|
|
|
|
//! assert_eq!(oid, vec![0x00, 0x01, 0x02, 0x03]);
|
|
|
|
//! Ok(())
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! [Object Identifiers]: https://en.wikipedia.org/wiki/Object_identifier
|
|
|
|
//! [ITU]: https://en.wikipedia.org/wiki/International_Telecommunications_Union
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
use std::borrow::Cow;
|
2022-05-05 15:50:44 +02:00
|
|
|
use crate::utils::varint::VarU128;
|
|
|
|
use rkyv::ser::Serializer;
|
2021-10-13 04:57:40 +02:00
|
|
|
use rkyv::vec::{ArchivedVec, VecResolver};
|
2022-05-05 15:50:44 +02:00
|
|
|
use rkyv::{Archive, Serialize};
|
2021-12-06 21:53:42 +01:00
|
|
|
use std::convert::TryFrom;
|
2022-05-05 15:50:44 +02:00
|
|
|
use std::convert::TryInto;
|
2021-10-18 10:39:31 +02:00
|
|
|
use std::fmt;
|
|
|
|
use std::fmt::Formatter;
|
2022-05-05 15:50:44 +02:00
|
|
|
use std::ops::Deref;
|
2021-10-18 10:39:31 +02:00
|
|
|
use std::str::FromStr;
|
2021-10-13 04:57:40 +02:00
|
|
|
|
2021-10-18 10:39:31 +02:00
|
|
|
type Node = u128;
|
|
|
|
type VarNode = VarU128;
|
2021-10-13 04:57:40 +02:00
|
|
|
|
|
|
|
/// Convenience module for quickly importing the public interface (e.g., `use oid::prelude::*`)
|
|
|
|
pub mod prelude {
|
|
|
|
pub use super::ObjectIdentifier;
|
|
|
|
pub use super::ObjectIdentifierError;
|
2022-05-05 15:50:44 +02:00
|
|
|
pub use super::ObjectIdentifierRoot::*;
|
2021-10-13 04:57:40 +02:00
|
|
|
pub use core::convert::{TryFrom, TryInto};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
|
|
|
#[repr(u8)]
|
|
|
|
pub enum ObjectIdentifierRoot {
|
|
|
|
ItuT = 0,
|
|
|
|
Iso = 1,
|
|
|
|
JointIsoItuT = 2,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Into<String> for ObjectIdentifierRoot {
|
|
|
|
fn into(self) -> String {
|
|
|
|
format!("{}", self as u8)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<u8> for ObjectIdentifierRoot {
|
|
|
|
type Error = ObjectIdentifierError;
|
|
|
|
fn try_from(value: u8) -> Result<ObjectIdentifierRoot, Self::Error> {
|
|
|
|
match value {
|
|
|
|
0 => Ok(ObjectIdentifierRoot::ItuT),
|
|
|
|
1 => Ok(ObjectIdentifierRoot::Iso),
|
|
|
|
2 => Ok(ObjectIdentifierRoot::JointIsoItuT),
|
|
|
|
_ => Err(ObjectIdentifierError::IllegalRootNode),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Object Identifier Errors
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
|
|
|
pub enum ObjectIdentifierError {
|
|
|
|
/// Failed to parse OID due to illegal root node (must be 0-2 decimal)
|
|
|
|
IllegalRootNode,
|
|
|
|
/// Failed to parse OID due to illegal first node (must be 0-39 decimal)
|
|
|
|
IllegalFirstChildNode,
|
|
|
|
/// Failed to parse OID due to illegal child node value (except first node)
|
|
|
|
IllegalChildNodeValue,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Object Identifier (OID)
|
2021-10-18 10:39:31 +02:00
|
|
|
#[derive(Clone, Eq, PartialEq, Hash)]
|
|
|
|
#[repr(transparent)]
|
2024-05-24 12:48:58 +02:00
|
|
|
pub struct ObjectIdentifier<'a> {
|
|
|
|
nodes: Cow<'a, [u8]>,
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl<'a> ObjectIdentifier<'a> {
|
2021-10-18 10:39:31 +02:00
|
|
|
#[inline(always)]
|
2024-05-24 12:48:58 +02:00
|
|
|
pub const fn new_unchecked(nodes: Cow<'a, [u8]>) -> Self {
|
2021-10-18 10:39:31 +02:00
|
|
|
Self { nodes }
|
|
|
|
}
|
2024-05-24 12:48:58 +02:00
|
|
|
pub fn from_box(nodes: Cow<'a, [u8]>) -> Result<Self, ObjectIdentifierError> {
|
2021-10-18 10:39:31 +02:00
|
|
|
if nodes.len() < 1 {
|
|
|
|
return Err(ObjectIdentifierError::IllegalRootNode);
|
|
|
|
};
|
|
|
|
ObjectIdentifierRoot::try_from(nodes[0] / 40)?;
|
|
|
|
|
|
|
|
let mut parsing_big_int = false;
|
|
|
|
let mut big_int: Node = 0;
|
|
|
|
for i in 1..nodes.len() {
|
2022-05-05 15:50:44 +02:00
|
|
|
if !parsing_big_int && nodes[i] < 128 {
|
|
|
|
} else {
|
2021-10-18 10:39:31 +02:00
|
|
|
if big_int > 0 {
|
|
|
|
if big_int >= Node::MAX >> 7 {
|
|
|
|
return Err(ObjectIdentifierError::IllegalChildNodeValue);
|
|
|
|
}
|
|
|
|
big_int <<= 7;
|
|
|
|
};
|
|
|
|
big_int |= (nodes[i] & !0x80) as Node;
|
|
|
|
parsing_big_int = nodes[i] & 0x80 != 0;
|
|
|
|
}
|
|
|
|
if big_int > 0 && !parsing_big_int {
|
|
|
|
big_int = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(Self { nodes })
|
|
|
|
}
|
|
|
|
|
2022-05-05 15:50:44 +02:00
|
|
|
pub fn build<B: AsRef<[Node]>>(
|
|
|
|
root: ObjectIdentifierRoot,
|
|
|
|
first: u8,
|
|
|
|
children: B,
|
|
|
|
) -> Result<Self, ObjectIdentifierError> {
|
2021-10-18 10:39:31 +02:00
|
|
|
if first > 40 {
|
|
|
|
return Err(ObjectIdentifierError::IllegalFirstChildNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
let children = children.as_ref();
|
|
|
|
let mut vec = Vec::with_capacity(children.len() + 1);
|
|
|
|
vec.push((root as u8) * 40 + first);
|
|
|
|
for child in children {
|
|
|
|
let var: VarNode = child.into();
|
|
|
|
vec.extend_from_slice(var.as_bytes())
|
|
|
|
}
|
2022-05-05 15:50:44 +02:00
|
|
|
Ok(Self {
|
2024-05-24 12:48:58 +02:00
|
|
|
nodes: Cow::from(vec),
|
2022-05-05 15:50:44 +02:00
|
|
|
})
|
2021-10-18 10:39:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn root(&self) -> Result<ObjectIdentifierRoot, ObjectIdentifierError> {
|
|
|
|
ObjectIdentifierRoot::try_from(self.nodes[0] / 40)
|
|
|
|
}
|
2024-05-24 12:48:58 +02:00
|
|
|
|
2021-10-18 10:39:31 +02:00
|
|
|
#[inline(always)]
|
2024-05-24 12:48:58 +02:00
|
|
|
pub fn first_node(&self) -> u8 {
|
|
|
|
self.nodes.as_ref()[0] % 40
|
2021-10-18 10:39:31 +02:00
|
|
|
}
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn child_nodes(&self) -> &[u8] {
|
|
|
|
&self.nodes[1..]
|
|
|
|
}
|
|
|
|
#[inline(always)]
|
2024-05-24 12:48:58 +02:00
|
|
|
pub fn as_bytes(&self) -> &[u8] {
|
2021-10-18 10:39:31 +02:00
|
|
|
&self.nodes
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl Deref for ObjectIdentifier<'_> {
|
2021-10-18 10:39:31 +02:00
|
|
|
type Target = [u8];
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.nodes
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl FromStr for ObjectIdentifier<'static> {
|
2021-10-18 10:39:31 +02:00
|
|
|
type Err = ObjectIdentifierError;
|
|
|
|
|
|
|
|
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
|
|
|
let mut nodes = value.split(".");
|
2022-05-05 15:50:44 +02:00
|
|
|
let root = nodes
|
|
|
|
.next()
|
2021-10-18 10:39:31 +02:00
|
|
|
.and_then(|n| n.parse::<u8>().ok())
|
|
|
|
.and_then(|n| n.try_into().ok())
|
|
|
|
.ok_or(ObjectIdentifierError::IllegalRootNode)?;
|
|
|
|
|
2022-05-05 15:50:44 +02:00
|
|
|
let first = nodes
|
|
|
|
.next()
|
2021-10-18 10:39:31 +02:00
|
|
|
.and_then(|n| parse_string_first_node(n).ok())
|
|
|
|
.ok_or(ObjectIdentifierError::IllegalFirstChildNode)?;
|
|
|
|
|
|
|
|
let mut children = if let (_, Some(hint)) = nodes.size_hint() {
|
|
|
|
Vec::with_capacity(hint)
|
|
|
|
} else {
|
|
|
|
Vec::new()
|
|
|
|
};
|
|
|
|
|
|
|
|
for child in nodes.map(|n| n.parse().ok()) {
|
|
|
|
if let Some(c) = child {
|
|
|
|
children.push(c);
|
|
|
|
} else {
|
|
|
|
return Err(ObjectIdentifierError::IllegalChildNodeValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectIdentifier::build(root, first, children)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl fmt::Display for ObjectIdentifier<'_> {
|
2021-10-18 10:39:31 +02:00
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
|
|
let show: String = self.into();
|
|
|
|
write!(f, "{}", show)
|
|
|
|
}
|
|
|
|
}
|
2024-05-24 12:48:58 +02:00
|
|
|
impl fmt::Debug for ObjectIdentifier<'_> {
|
2021-10-18 10:39:31 +02:00
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
|
|
let show: String = self.into();
|
|
|
|
write!(f, "{}", show)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(transparent)]
|
|
|
|
pub struct ArchivedObjectIdentifier {
|
2022-05-05 15:50:44 +02:00
|
|
|
archived: ArchivedVec<u8>,
|
2021-10-18 10:39:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Deref for ArchivedObjectIdentifier {
|
|
|
|
type Target = [u8];
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
self.archived.as_slice()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for ArchivedObjectIdentifier {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
2022-05-05 15:50:44 +02:00
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"{}",
|
|
|
|
&convert_to_string(self.archived.as_slice())
|
|
|
|
.unwrap_or_else(|e| format!("Invalid OID: {:?}", e))
|
|
|
|
)
|
2021-10-18 10:39:31 +02:00
|
|
|
}
|
|
|
|
}
|
2021-10-13 04:57:40 +02:00
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl Archive for ObjectIdentifier<'_> {
|
2021-10-18 10:39:31 +02:00
|
|
|
type Archived = ArchivedObjectIdentifier;
|
|
|
|
type Resolver = VecResolver;
|
|
|
|
|
|
|
|
unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
|
|
|
|
let (oid_pos, oid_out) = rkyv::out_field!(out.archived);
|
|
|
|
ArchivedVec::resolve_from_slice(self.nodes.as_ref(), pos + oid_pos, resolver, oid_out);
|
|
|
|
}
|
|
|
|
}
|
2024-05-24 12:48:58 +02:00
|
|
|
impl Archive for &'static ObjectIdentifier<'_> {
|
2021-10-18 10:39:31 +02:00
|
|
|
type Archived = ArchivedObjectIdentifier;
|
2021-10-13 04:57:40 +02:00
|
|
|
type Resolver = VecResolver;
|
|
|
|
|
|
|
|
unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
|
2021-10-18 10:39:31 +02:00
|
|
|
let (oid_pos, oid_out) = rkyv::out_field!(out.archived);
|
|
|
|
ArchivedVec::resolve_from_slice(self.nodes.as_ref(), pos + oid_pos, resolver, oid_out);
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl<S: Serializer + ?Sized> Serialize<S> for ObjectIdentifier<'_>
|
2022-05-05 15:50:44 +02:00
|
|
|
where
|
|
|
|
[u8]: rkyv::SerializeUnsized<S>,
|
2021-10-13 04:57:40 +02:00
|
|
|
{
|
|
|
|
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
|
2021-10-18 10:39:31 +02:00
|
|
|
ArchivedVec::serialize_from_slice(self.nodes.as_ref(), serializer)
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-18 10:39:31 +02:00
|
|
|
fn parse_string_first_node(first_child_node: &str) -> Result<u8, ObjectIdentifierError> {
|
|
|
|
let first_child_node: u8 = first_child_node
|
|
|
|
.parse()
|
|
|
|
.map_err(|_| ObjectIdentifierError::IllegalFirstChildNode)?;
|
|
|
|
if first_child_node > 39 {
|
|
|
|
return Err(ObjectIdentifierError::IllegalFirstChildNode);
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
2021-10-18 10:39:31 +02:00
|
|
|
Ok(first_child_node)
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl ObjectIdentifier<'static> {
|
|
|
|
fn from_string<S>(value: S) -> Result<Self, ObjectIdentifierError>
|
2021-10-13 04:57:40 +02:00
|
|
|
where
|
2021-10-18 10:39:31 +02:00
|
|
|
S: AsRef<str>,
|
2021-10-13 04:57:40 +02:00
|
|
|
{
|
2021-10-18 10:39:31 +02:00
|
|
|
ObjectIdentifier::from_str(value.as_ref())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn convert_to_string(nodes: &[u8]) -> Result<String, ObjectIdentifierError> {
|
|
|
|
assert!(nodes.len() > 0);
|
|
|
|
let root = nodes[0] / 40;
|
|
|
|
let mut out = root.to_string();
|
|
|
|
|
|
|
|
out.push('.');
|
|
|
|
let first = nodes[0] % 40;
|
|
|
|
out.extend(first.to_string().chars());
|
|
|
|
|
|
|
|
let mut parsing_big_int = false;
|
|
|
|
let mut big_int: Node = 0;
|
|
|
|
for i in 1..nodes.len() {
|
|
|
|
if !parsing_big_int && nodes[i] < 128 {
|
|
|
|
// less than 7 bit of node value
|
|
|
|
out.push('.');
|
|
|
|
let nr = nodes[i].to_string();
|
|
|
|
out.extend(nr.chars());
|
|
|
|
} else {
|
|
|
|
if big_int > 0 {
|
|
|
|
if big_int >= Node::MAX >> 7 {
|
|
|
|
return Err(ObjectIdentifierError::IllegalChildNodeValue);
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
2021-10-18 10:39:31 +02:00
|
|
|
big_int <<= 7;
|
|
|
|
};
|
|
|
|
big_int += (nodes[i] & !0x80) as Node;
|
|
|
|
parsing_big_int = nodes[i] & 0x80 != 0;
|
|
|
|
}
|
|
|
|
if big_int > 0 && !parsing_big_int {
|
|
|
|
out.push('.');
|
|
|
|
out.extend(big_int.to_string().chars());
|
|
|
|
big_int = 0;
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
|
|
|
}
|
2021-10-18 10:39:31 +02:00
|
|
|
|
|
|
|
Ok(out)
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl Into<String> for &ObjectIdentifier<'_> {
|
2021-10-13 04:57:40 +02:00
|
|
|
fn into(self) -> String {
|
2022-05-05 15:50:44 +02:00
|
|
|
convert_to_string(&self.nodes).expect("Valid OID object couldn't be serialized.")
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl Into<String> for ObjectIdentifier <'_>{
|
2021-10-13 04:57:40 +02:00
|
|
|
fn into(self) -> String {
|
|
|
|
(&self).into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl<'a> Into<&'a [u8]> for &'a ObjectIdentifier<'_> {
|
2021-10-18 10:39:31 +02:00
|
|
|
fn into(self) -> &'a [u8] {
|
|
|
|
&self.nodes
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl Into<Vec<u8>> for ObjectIdentifier<'_> {
|
2021-10-13 04:57:40 +02:00
|
|
|
fn into(self) -> Vec<u8> {
|
2024-05-24 12:48:58 +02:00
|
|
|
self.nodes.into()
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl TryFrom<&str> for ObjectIdentifier<'static> {
|
2021-10-13 04:57:40 +02:00
|
|
|
type Error = ObjectIdentifierError;
|
2024-05-24 12:48:58 +02:00
|
|
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
2021-10-13 04:57:40 +02:00
|
|
|
ObjectIdentifier::from_string(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl TryFrom<String> for ObjectIdentifier<'static> {
|
2021-10-13 04:57:40 +02:00
|
|
|
type Error = ObjectIdentifierError;
|
2024-05-24 12:48:58 +02:00
|
|
|
fn try_from(value: String) -> Result<Self, Self::Error> {
|
2021-10-13 04:57:40 +02:00
|
|
|
ObjectIdentifier::from_string(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl<'a> TryFrom<&'a [u8]> for ObjectIdentifier<'a> {
|
2021-10-13 04:57:40 +02:00
|
|
|
type Error = ObjectIdentifierError;
|
2024-05-24 12:48:58 +02:00
|
|
|
fn try_from(nodes: &'a [u8]) -> Result<Self, Self::Error> {
|
|
|
|
Self::from_box(Cow::Borrowed(nodes))
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl TryFrom<Vec<u8>> for ObjectIdentifier<'static> {
|
2021-10-13 04:57:40 +02:00
|
|
|
type Error = ObjectIdentifierError;
|
2024-05-24 12:48:58 +02:00
|
|
|
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
|
|
|
|
Self::from_box(Cow::from(value))
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mod serde_support {
|
|
|
|
use super::*;
|
|
|
|
use core::fmt;
|
|
|
|
use serde::{de, ser};
|
|
|
|
|
|
|
|
struct OidVisitor;
|
|
|
|
|
|
|
|
impl<'de> de::Visitor<'de> for OidVisitor {
|
2024-05-24 12:48:58 +02:00
|
|
|
type Value = ObjectIdentifier<'de>;
|
2021-10-13 04:57:40 +02:00
|
|
|
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
formatter.write_str("a valid buffer representing an OID")
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
|
2021-10-13 04:57:40 +02:00
|
|
|
where
|
|
|
|
E: de::Error,
|
|
|
|
{
|
2024-05-24 12:48:58 +02:00
|
|
|
ObjectIdentifier::try_from(v).map_err(move |err| {
|
2021-10-13 04:57:40 +02:00
|
|
|
E::invalid_value(
|
|
|
|
de::Unexpected::Other(match err {
|
|
|
|
ObjectIdentifierError::IllegalRootNode => "illegal root node",
|
|
|
|
ObjectIdentifierError::IllegalFirstChildNode => "illegal first child node",
|
|
|
|
ObjectIdentifierError::IllegalChildNodeValue => "illegal child node value",
|
|
|
|
}),
|
|
|
|
&"a valid buffer representing an OID",
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: de::Error,
|
|
|
|
{
|
|
|
|
ObjectIdentifier::try_from(v).map_err(|err| {
|
|
|
|
E::invalid_value(
|
|
|
|
de::Unexpected::Other(match err {
|
|
|
|
ObjectIdentifierError::IllegalRootNode => "illegal root node",
|
|
|
|
ObjectIdentifierError::IllegalFirstChildNode => "illegal first child node",
|
|
|
|
ObjectIdentifierError::IllegalChildNodeValue => "illegal child node value",
|
|
|
|
}),
|
|
|
|
&"a string representing an OID",
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl<'de> de::Deserialize<'de> for ObjectIdentifier<'de> {
|
|
|
|
fn deserialize<D>(deserializer: D) -> Result<ObjectIdentifier<'de>, D::Error>
|
2021-10-13 04:57:40 +02:00
|
|
|
where
|
|
|
|
D: de::Deserializer<'de>,
|
|
|
|
{
|
|
|
|
if deserializer.is_human_readable() {
|
|
|
|
deserializer.deserialize_str(OidVisitor)
|
|
|
|
} else {
|
|
|
|
deserializer.deserialize_bytes(OidVisitor)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
impl ser::Serialize for ObjectIdentifier<'_> {
|
2021-10-13 04:57:40 +02:00
|
|
|
fn serialize<S>(
|
|
|
|
&self,
|
|
|
|
serializer: S,
|
|
|
|
) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
|
|
|
|
where
|
|
|
|
S: ser::Serializer,
|
|
|
|
{
|
|
|
|
if serializer.is_human_readable() {
|
|
|
|
let encoded: String = self.into();
|
|
|
|
serializer.serialize_str(&encoded)
|
|
|
|
} else {
|
2021-10-18 10:39:31 +02:00
|
|
|
serializer.serialize_bytes(self.as_bytes())
|
2021-10-20 20:56:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl ser::Serialize for ArchivedObjectIdentifier {
|
2022-05-05 15:50:44 +02:00
|
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
|
|
where
|
|
|
|
S: ser::Serializer,
|
2021-10-20 20:56:47 +02:00
|
|
|
{
|
|
|
|
if serializer.is_human_readable() {
|
2022-05-05 15:50:44 +02:00
|
|
|
let encoded: String =
|
|
|
|
convert_to_string(self.deref()).expect("Failed to convert valid OID to String");
|
2021-10-20 20:56:47 +02:00
|
|
|
serializer.serialize_str(&encoded)
|
|
|
|
} else {
|
|
|
|
serializer.serialize_bytes(self.deref())
|
2021-10-13 04:57:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:48:58 +02:00
|
|
|
/// Helper macro to declare Object Identifiers at compile-time
|
|
|
|
///
|
|
|
|
/// Since the DER encoded oids are not very readable we provide a
|
|
|
|
/// procedural macro `oid!`. The macro can be used the following ways:
|
|
|
|
///
|
|
|
|
/// - `oid!(1.4.42.23)`: Create a const expression for the corresponding `Oid<'static>`
|
|
|
|
/// - `oid!(rel 42.23)`: Create a const expression for the corresponding relative `Oid<'static>`
|
|
|
|
/// - `oid!(raw 1.4.42.23)`/`oid!(raw rel 42.23)`: Obtain the DER encoded form as a byte array.
|
|
|
|
///
|
|
|
|
/// # Comparing oids
|
|
|
|
///
|
|
|
|
/// Comparing a parsed oid to a static oid is probably the most common
|
|
|
|
/// thing done with oids in your code. The `oid!` macro can be used in expression positions for
|
|
|
|
/// this purpose. For example
|
|
|
|
/// ```
|
|
|
|
/// use diflouroborane::oid;
|
|
|
|
/// use diflouroborane::utils::oid::ObjectIdentifier;
|
|
|
|
///
|
|
|
|
/// # let some_oid: ObjectIdentifier = oid!(1.2.456);
|
|
|
|
/// const SOME_STATIC_OID: ObjectIdentifier = oid!(1.2.456);
|
|
|
|
/// assert_eq!(some_oid, SOME_STATIC_OID)
|
|
|
|
/// ```
|
|
|
|
/// To get a relative Oid use `oid!(rel 1.2)`.
|
|
|
|
///
|
|
|
|
/// Because of limitations for procedural macros ([rust issue](https://github.com/rust-lang/rust/issues/54727))
|
|
|
|
/// and constants used in patterns ([rust issue](https://github.com/rust-lang/rust/issues/31434))
|
|
|
|
/// the `oid` macro can not directly be used in patterns, also not through constants.
|
|
|
|
/// You can do this, though:
|
|
|
|
/// ```
|
|
|
|
/// # use diflouroborane::oid;
|
|
|
|
/// # use diflouroborane::utils::oid::ObjectIdentifier;
|
|
|
|
/// # let some_oid: ObjectIdentifier<'static> = oid!(1.2.456);
|
|
|
|
/// const SOME_OID: ObjectIdentifier<'static> = oid!(1.2.456);
|
|
|
|
/// if some_oid == SOME_OID || some_oid == oid!(1.2.456) {
|
|
|
|
/// println!("match");
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// // Alternatively, compare the DER encoded form directly:
|
|
|
|
/// const SOME_OID_RAW: &[u8] = &oid!(raw 1.2.456);
|
|
|
|
/// match some_oid.as_bytes() {
|
|
|
|
/// SOME_OID_RAW => println!("match"),
|
|
|
|
/// _ => panic!("no match"),
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
/// *Attention*, be aware that the latter version might not handle the case of a relative oid correctly. An
|
|
|
|
/// extra check might be necessary.
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! oid {
|
|
|
|
(raw $( $item:literal ).*) => {
|
|
|
|
::bffh_impl::encode_oid!( $( $item ).* )
|
|
|
|
};
|
|
|
|
(raw $items:expr) => {
|
|
|
|
::bffh_impl::encode_oid!($items)
|
|
|
|
};
|
|
|
|
($($item:literal ).*) => {
|
|
|
|
$crate::utils::oid::ObjectIdentifier::new_unchecked(::std::borrow::Cow::Borrowed(
|
|
|
|
&$crate::oid!(raw $( $item ).*),
|
|
|
|
))
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-10-13 04:57:40 +02:00
|
|
|
#[cfg(test)]
|
2021-10-27 21:32:50 +02:00
|
|
|
pub(crate) mod tests {
|
2021-10-13 04:57:40 +02:00
|
|
|
use super::*;
|
2021-10-18 10:39:31 +02:00
|
|
|
use std::convert::TryInto;
|
2021-10-13 04:57:40 +02:00
|
|
|
|
2021-10-27 21:32:50 +02:00
|
|
|
pub(crate) fn gen_random() -> ObjectIdentifier {
|
|
|
|
let amt: u8 = rand::random::<u8>() % 10 + 1;
|
|
|
|
let mut children = Vec::new();
|
2021-10-28 01:10:35 +02:00
|
|
|
for _ in 0..amt {
|
2021-10-27 21:32:50 +02:00
|
|
|
children.push(rand::random());
|
|
|
|
}
|
|
|
|
|
2022-05-05 15:50:44 +02:00
|
|
|
ObjectIdentifier::build(ObjectIdentifierRoot::JointIsoItuT, 25, children).unwrap()
|
2021-10-27 21:32:50 +02:00
|
|
|
}
|
|
|
|
|
2021-10-13 04:57:40 +02:00
|
|
|
#[test]
|
|
|
|
fn encode_binary_root_node_0() {
|
|
|
|
let expected: Vec<u8> = vec![0];
|
2022-05-05 15:50:44 +02:00
|
|
|
let oid = ObjectIdentifier::build(ObjectIdentifierRoot::ItuT, 0x00, vec![]).unwrap();
|
2021-10-18 10:39:31 +02:00
|
|
|
let actual: Vec<u8> = oid.into();
|
2021-10-13 04:57:40 +02:00
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn encode_binary_root_node_1() {
|
|
|
|
let expected: Vec<u8> = vec![40];
|
2022-05-05 15:50:44 +02:00
|
|
|
let oid = ObjectIdentifier::build(ObjectIdentifierRoot::Iso, 0x00, vec![]).unwrap();
|
2021-10-18 10:39:31 +02:00
|
|
|
let actual: Vec<u8> = oid.into();
|
2021-10-13 04:57:40 +02:00
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn encode_binary_root_node_2() {
|
|
|
|
let expected: Vec<u8> = vec![80];
|
2022-05-05 15:50:44 +02:00
|
|
|
let oid =
|
|
|
|
ObjectIdentifier::build(ObjectIdentifierRoot::JointIsoItuT, 0x00, vec![]).unwrap();
|
2021-10-18 10:39:31 +02:00
|
|
|
let actual: Vec<u8> = oid.into();
|
2021-10-13 04:57:40 +02:00
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn encode_binary_example_1() {
|
|
|
|
let expected: Vec<u8> = vec![0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0D, 0x15];
|
2021-10-18 10:39:31 +02:00
|
|
|
let oid = ObjectIdentifier::build(
|
|
|
|
ObjectIdentifierRoot::ItuT,
|
|
|
|
0x01,
|
|
|
|
vec![1, 2, 3, 5, 8, 13, 21],
|
2022-05-05 15:50:44 +02:00
|
|
|
)
|
|
|
|
.unwrap();
|
2021-10-18 10:39:31 +02:00
|
|
|
let actual: Vec<u8> = oid.into();
|
2021-10-13 04:57:40 +02:00
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn encode_binary_example_2() {
|
|
|
|
let expected: Vec<u8> = vec![
|
|
|
|
0x77, 0x2A, 0x93, 0x45, 0x83, 0xFF, 0x7F, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x89, 0x53,
|
|
|
|
0x92, 0x30,
|
|
|
|
];
|
2021-10-18 10:39:31 +02:00
|
|
|
let oid = ObjectIdentifier::build(
|
|
|
|
ObjectIdentifierRoot::JointIsoItuT,
|
|
|
|
39,
|
|
|
|
vec![42, 2501, 65535, 2147483647, 1235, 2352],
|
2022-05-05 15:50:44 +02:00
|
|
|
)
|
|
|
|
.unwrap();
|
2021-10-18 10:39:31 +02:00
|
|
|
let actual: Vec<u8> = (oid).into();
|
2021-10-13 04:57:40 +02:00
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn encode_string_root_node_0() {
|
|
|
|
let expected = "0.0";
|
2022-05-05 15:50:44 +02:00
|
|
|
let oid = ObjectIdentifier::build(ObjectIdentifierRoot::ItuT, 0x00, vec![]).unwrap();
|
2021-10-18 10:39:31 +02:00
|
|
|
let actual: String = (oid).into();
|
2021-10-13 04:57:40 +02:00
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn encode_string_root_node_1() {
|
|
|
|
let expected = "1.0";
|
2022-05-05 15:50:44 +02:00
|
|
|
let oid = ObjectIdentifier::build(ObjectIdentifierRoot::Iso, 0x00, vec![]).unwrap();
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual: String = (&oid).into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn encode_string_root_node_2() {
|
|
|
|
let expected = "2.0";
|
2022-05-05 15:50:44 +02:00
|
|
|
let oid =
|
|
|
|
ObjectIdentifier::build(ObjectIdentifierRoot::JointIsoItuT, 0x00, vec![]).unwrap();
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual: String = (&oid).into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn encode_string_example_1() {
|
|
|
|
let expected = "0.1.1.2.3.5.8.13.21";
|
2021-10-18 10:39:31 +02:00
|
|
|
let oid = ObjectIdentifier::build(
|
|
|
|
ObjectIdentifierRoot::ItuT,
|
|
|
|
0x01,
|
|
|
|
vec![1, 2, 3, 5, 8, 13, 21],
|
2022-05-05 15:50:44 +02:00
|
|
|
)
|
|
|
|
.unwrap();
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual: String = (&oid).into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn encode_string_example_2() {
|
|
|
|
let expected = "2.39.42.2501.65535.2147483647.1235.2352";
|
2021-10-18 10:39:31 +02:00
|
|
|
let oid = ObjectIdentifier::build(
|
|
|
|
ObjectIdentifierRoot::JointIsoItuT,
|
|
|
|
39,
|
|
|
|
vec![42, 2501, 65535, 2147483647, 1235, 2352],
|
2022-05-05 15:50:44 +02:00
|
|
|
)
|
|
|
|
.unwrap();
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual: String = (&oid).into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_binary_root_node_0() {
|
2022-05-05 15:50:44 +02:00
|
|
|
let expected = ObjectIdentifier::build(ObjectIdentifierRoot::ItuT, 0x00, vec![]);
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual = vec![0x00].try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_binary_root_node_1() {
|
2022-05-05 15:50:44 +02:00
|
|
|
let expected = ObjectIdentifier::build(ObjectIdentifierRoot::Iso, 0x00, vec![]);
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual = vec![40].try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_binary_root_node_2() {
|
2022-05-05 15:50:44 +02:00
|
|
|
let expected = ObjectIdentifier::build(ObjectIdentifierRoot::JointIsoItuT, 0x00, vec![]);
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual = vec![80].try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_binary_example_1() {
|
2021-10-18 10:39:31 +02:00
|
|
|
let expected = ObjectIdentifier::build(
|
|
|
|
ObjectIdentifierRoot::ItuT,
|
|
|
|
0x01,
|
|
|
|
vec![1, 2, 3, 5, 8, 13, 21],
|
|
|
|
);
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual = vec![0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0D, 0x15].try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_binary_example_2() {
|
2021-10-18 10:39:31 +02:00
|
|
|
let expected = ObjectIdentifier::build(
|
|
|
|
ObjectIdentifierRoot::JointIsoItuT,
|
|
|
|
39,
|
|
|
|
vec![42, 2501, 65535, 2147483647, 1235, 2352],
|
|
|
|
);
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual = vec![
|
|
|
|
0x77, 0x2A, 0x93, 0x45, 0x83, 0xFF, 0x7F, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x89, 0x53,
|
|
|
|
0x92, 0x30,
|
|
|
|
]
|
|
|
|
.try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_string_root_node_0() {
|
2022-05-05 15:50:44 +02:00
|
|
|
let expected = ObjectIdentifier::build(ObjectIdentifierRoot::ItuT, 0x00, vec![]);
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual = "0.0".try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_string_root_node_1() {
|
2022-05-05 15:50:44 +02:00
|
|
|
let expected = ObjectIdentifier::build(ObjectIdentifierRoot::Iso, 0x00, vec![]);
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual = "1.0".try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_string_root_node_2() {
|
2022-05-05 15:50:44 +02:00
|
|
|
let expected = ObjectIdentifier::build(ObjectIdentifierRoot::JointIsoItuT, 0x00, vec![]);
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual = "2.0".try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_string_example_1() {
|
2021-10-18 10:39:31 +02:00
|
|
|
let expected = ObjectIdentifier::build(
|
|
|
|
ObjectIdentifierRoot::ItuT,
|
|
|
|
0x01,
|
|
|
|
vec![1, 2, 3, 5, 8, 13, 21],
|
|
|
|
);
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual = "0.1.1.2.3.5.8.13.21".try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_string_example_2() {
|
2021-10-18 10:39:31 +02:00
|
|
|
let expected = ObjectIdentifier::build(
|
|
|
|
ObjectIdentifierRoot::JointIsoItuT,
|
|
|
|
39,
|
|
|
|
vec![42, 2501, 65535, 2147483647, 1235, 2352],
|
|
|
|
);
|
2021-10-13 04:57:40 +02:00
|
|
|
let actual = "2.39.42.2501.65535.2147483647.1235.2352".try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn illegal_oid_root() {
|
|
|
|
let expected = Err(ObjectIdentifierError::IllegalRootNode);
|
|
|
|
for i in 3..core::u8::MAX {
|
|
|
|
let actual = ObjectIdentifierRoot::try_from(i);
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn illegal_first_node_too_large() {
|
|
|
|
let expected = Err(ObjectIdentifierError::IllegalFirstChildNode);
|
|
|
|
for i in 40..core::u8::MAX {
|
|
|
|
let string_val = format!("{}.2.3.4", i);
|
|
|
|
let mut nodes_iter = string_val.split(".");
|
2021-10-18 10:39:31 +02:00
|
|
|
let actual = parse_string_first_node(nodes_iter.next().unwrap());
|
2021-10-13 04:57:40 +02:00
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn illegal_first_node_empty() {
|
|
|
|
let expected = Err(ObjectIdentifierError::IllegalFirstChildNode);
|
|
|
|
let string_val = String::new();
|
|
|
|
let mut nodes_iter = string_val.split(".");
|
2021-10-18 10:39:31 +02:00
|
|
|
let actual = parse_string_first_node(nodes_iter.next().unwrap());
|
2021-10-13 04:57:40 +02:00
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn illegal_first_node_large() {
|
|
|
|
let expected = Err(ObjectIdentifierError::IllegalFirstChildNode);
|
|
|
|
let string_val = String::from("40");
|
|
|
|
let mut nodes_iter = string_val.split(".");
|
2021-10-18 10:39:31 +02:00
|
|
|
let actual = parse_string_first_node(nodes_iter.next().unwrap());
|
2021-10-13 04:57:40 +02:00
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_string_crap() {
|
|
|
|
let expected: Result<ObjectIdentifier, ObjectIdentifierError> =
|
|
|
|
Err(ObjectIdentifierError::IllegalRootNode);
|
|
|
|
let actual = "wtf".try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_string_empty() {
|
|
|
|
let expected: Result<ObjectIdentifier, ObjectIdentifierError> =
|
|
|
|
Err(ObjectIdentifierError::IllegalRootNode);
|
|
|
|
let actual = String::new().try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_binary_empty() {
|
|
|
|
let expected: Result<ObjectIdentifier, ObjectIdentifierError> =
|
|
|
|
Err(ObjectIdentifierError::IllegalRootNode);
|
|
|
|
let actual = vec![].try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_binary_example_over_u128() {
|
|
|
|
let expected: Result<ObjectIdentifier, ObjectIdentifierError> =
|
|
|
|
Err(ObjectIdentifierError::IllegalChildNodeValue);
|
|
|
|
let actual = vec![
|
|
|
|
0x00, 0x89, 0x97, 0xBF, 0xA3, 0xB8, 0xE8, 0xB3, 0xE6, 0xFB, 0xF2, 0xEA, 0xC3, 0xCA,
|
|
|
|
0xF2, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F,
|
|
|
|
]
|
|
|
|
.try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
#[test]
|
|
|
|
fn parse_string_root_node_3plus() {
|
|
|
|
for i in 3..=core::u8::MAX {
|
|
|
|
let expected: Result<ObjectIdentifier, ObjectIdentifierError> =
|
|
|
|
Err(ObjectIdentifierError::IllegalRootNode);
|
|
|
|
let actual = format!("{}", i).try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_string_example_over_u128() {
|
|
|
|
let expected: Result<ObjectIdentifier, ObjectIdentifierError> =
|
|
|
|
Err(ObjectIdentifierError::IllegalChildNodeValue);
|
|
|
|
let actual = "1.1.349239782398732987223423423423423423423423423423434982342342342342342342324523453452345234523452345234523452345234537234987234".try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_string_example_first_node_over_39() {
|
|
|
|
let expected: Result<ObjectIdentifier, ObjectIdentifierError> =
|
|
|
|
Err(ObjectIdentifierError::IllegalFirstChildNode);
|
|
|
|
let actual = "1.40.1.2.3".try_into();
|
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
2021-10-28 01:10:35 +02:00
|
|
|
#[test]
|
|
|
|
fn parse_string_large_children_ok() {
|
2022-05-05 15:50:44 +02:00
|
|
|
let expected = ObjectIdentifier::build(
|
|
|
|
ObjectIdentifierRoot::JointIsoItuT,
|
|
|
|
25,
|
|
|
|
vec![
|
|
|
|
190754093376743485973207716749546715206,
|
|
|
|
255822649272987943607843257596365752308,
|
|
|
|
15843412533224453995377625663329542022,
|
|
|
|
6457999595881951503805148772927347934,
|
|
|
|
19545192863105095042881850060069531734,
|
|
|
|
195548685662657784196186957311035194990,
|
|
|
|
233020488258340943072303499291936117654,
|
|
|
|
193307160423854019916786016773068715190,
|
|
|
|
],
|
|
|
|
)
|
|
|
|
.unwrap();
|
2021-10-28 01:10:35 +02:00
|
|
|
let actual = "2.25.190754093376743485973207716749546715206.\
|
|
|
|
255822649272987943607843257596365752308.\
|
|
|
|
15843412533224453995377625663329542022.\
|
|
|
|
6457999595881951503805148772927347934.\
|
|
|
|
19545192863105095042881850060069531734.\
|
|
|
|
195548685662657784196186957311035194990.\
|
|
|
|
233020488258340943072303499291936117654.\
|
2022-05-05 15:50:44 +02:00
|
|
|
193307160423854019916786016773068715190"
|
|
|
|
.try_into()
|
|
|
|
.unwrap();
|
2021-10-28 01:10:35 +02:00
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
2021-10-13 04:57:40 +02:00
|
|
|
#[test]
|
|
|
|
fn encode_to_string() {
|
|
|
|
let expected = String::from("1.2.3.4");
|
2022-05-05 15:50:44 +02:00
|
|
|
let actual: String = ObjectIdentifier::build(ObjectIdentifierRoot::Iso, 2, vec![3, 4])
|
|
|
|
.unwrap()
|
|
|
|
.into();
|
2021-10-13 04:57:40 +02:00
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn encode_to_bytes() {
|
|
|
|
let expected = vec![0x2A, 0x03, 0x04];
|
2022-05-05 15:50:44 +02:00
|
|
|
let actual: Vec<u8> = ObjectIdentifier::build(ObjectIdentifierRoot::Iso, 2, vec![3, 4])
|
|
|
|
.unwrap()
|
|
|
|
.into();
|
2021-10-13 04:57:40 +02:00
|
|
|
assert_eq!(expected, actual);
|
|
|
|
}
|
2022-05-05 15:50:44 +02:00
|
|
|
}
|