1use crate::{
4 DecodeValue, EncodeValue, Error, FixedTag, Header, Length, Reader, Result, Tag, Tagged, Writer,
5 asn1::AnyRef, ord::OrdIsValueOrd,
6};
7use const_oid::{ObjectIdentifier, ObjectIdentifierRef};
8
9#[cfg(feature = "alloc")]
10use super::Any;
11
12impl<'a, const MAX_SIZE: usize> DecodeValue<'a> for ObjectIdentifier<MAX_SIZE> {
13 type Error = Error;
14
15 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
16 let mut buf = [0u8; MAX_SIZE];
17 let slice = buf
18 .get_mut(..header.length().try_into()?)
19 .ok_or_else(|| reader.error(Self::TAG.length_error()))?;
20
21 let actual_len = reader.read_into(slice)?.len();
22 debug_assert_eq!(actual_len, header.length().try_into()?);
23
24 ObjectIdentifierRef::from_bytes(slice)
25 .and_then(TryInto::try_into)
26 .map_err(|oid_err| reader.error(Error::from(oid_err).kind()))
27 }
28}
29
30impl<const MAX_SIZE: usize> EncodeValue for ObjectIdentifier<MAX_SIZE> {
31 fn value_len(&self) -> Result<Length> {
32 Length::try_from(self.as_bytes().len())
33 }
34
35 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
36 writer.write(self.as_bytes())
37 }
38}
39
40impl<const MAX_SIZE: usize> FixedTag for ObjectIdentifier<MAX_SIZE> {
41 const TAG: Tag = Tag::ObjectIdentifier;
42}
43
44impl<const MAX_SIZE: usize> OrdIsValueOrd for ObjectIdentifier<MAX_SIZE> {}
45
46impl<'a, const MAX_SIZE: usize> From<&'a ObjectIdentifier<MAX_SIZE>> for AnyRef<'a> {
47 fn from(oid: &'a ObjectIdentifier<MAX_SIZE>) -> AnyRef<'a> {
48 let value = oid
53 .as_bytes()
54 .try_into()
55 .expect("OID length invariant violated");
56
57 AnyRef::from_tag_and_value(Tag::ObjectIdentifier, value)
58 }
59}
60
61#[cfg(feature = "alloc")]
62impl<const MAX_SIZE: usize> From<ObjectIdentifier<MAX_SIZE>> for Any {
63 fn from(oid: ObjectIdentifier<MAX_SIZE>) -> Any {
64 AnyRef::from(&oid).into()
65 }
66}
67
68impl<const MAX_SIZE: usize> TryFrom<AnyRef<'_>> for ObjectIdentifier<MAX_SIZE> {
69 type Error = Error;
70
71 fn try_from(any: AnyRef<'_>) -> Result<ObjectIdentifier<MAX_SIZE>> {
72 any.tag().assert_eq(Tag::ObjectIdentifier)?;
73 Ok(ObjectIdentifierRef::from_bytes(any.value())?.try_into()?)
74 }
75}
76
77#[cfg(test)]
78#[allow(clippy::unwrap_used)]
79mod tests {
80 use super::ObjectIdentifier;
81 use crate::{Decode, Encode, Length};
82
83 const EXAMPLE_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549");
84 const EXAMPLE_OID_BYTES: &[u8; 8] = &[0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d];
85
86 #[test]
87 fn decode() {
88 let oid = ObjectIdentifier::from_der(EXAMPLE_OID_BYTES).unwrap();
89 assert_eq!(EXAMPLE_OID, oid);
90 }
91
92 #[test]
93 fn encode() {
94 let mut buffer = [0u8; 8];
95 assert_eq!(
96 EXAMPLE_OID_BYTES,
97 EXAMPLE_OID.encode_to_slice(&mut buffer).unwrap()
98 );
99 }
100
101 #[test]
102 fn length() {
103 assert!(ObjectIdentifier::MAX_SIZE <= Length::MAX.try_into().unwrap());
105 }
106}