| //! ASN.1 `OBJECT IDENTIFIER` | |
| use crate::{ | |
| asn1::AnyRef, ord::OrdIsValueOrd, DecodeValue, EncodeValue, Error, FixedTag, Header, Length, | |
| Reader, Result, Tag, Tagged, Writer, | |
| }; | |
| use const_oid::ObjectIdentifier; | |
| impl<'a> DecodeValue<'a> for ObjectIdentifier { | |
| fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { | |
| let mut buf = [0u8; ObjectIdentifier::MAX_SIZE]; | |
| let slice = buf | |
| .get_mut(..header.length.try_into()?) | |
| .ok_or_else(|| Self::TAG.length_error())?; | |
| let actual_len = reader.read_into(slice)?.len(); | |
| debug_assert_eq!(actual_len, header.length.try_into()?); | |
| Ok(Self::from_bytes(slice)?) | |
| } | |
| } | |
| impl EncodeValue for ObjectIdentifier { | |
| fn value_len(&self) -> Result<Length> { | |
| Length::try_from(self.as_bytes().len()) | |
| } | |
| fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { | |
| writer.write(self.as_bytes()) | |
| } | |
| } | |
| impl FixedTag for ObjectIdentifier { | |
| const TAG: Tag = Tag::ObjectIdentifier; | |
| } | |
| impl OrdIsValueOrd for ObjectIdentifier {} | |
| impl<'a> From<&'a ObjectIdentifier> for AnyRef<'a> { | |
| fn from(oid: &'a ObjectIdentifier) -> AnyRef<'a> { | |
| // Note: ensuring an infallible conversion is possible relies on the | |
| // invariant that `const_oid::MAX_LEN <= Length::max()`. | |
| // | |
| // The `length()` test below ensures this is the case. | |
| let value = oid | |
| .as_bytes() | |
| .try_into() | |
| .expect("OID length invariant violated"); | |
| AnyRef::from_tag_and_value(Tag::ObjectIdentifier, value) | |
| } | |
| } | |
| impl TryFrom<AnyRef<'_>> for ObjectIdentifier { | |
| type Error = Error; | |
| fn try_from(any: AnyRef<'_>) -> Result<ObjectIdentifier> { | |
| any.tag().assert_eq(Tag::ObjectIdentifier)?; | |
| Ok(ObjectIdentifier::from_bytes(any.value())?) | |
| } | |
| } | |
| #[cfg(test)] | |
| mod tests { | |
| use super::ObjectIdentifier; | |
| use crate::{Decode, Encode, Length}; | |
| const EXAMPLE_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549"); | |
| const EXAMPLE_OID_BYTES: &[u8; 8] = &[0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d]; | |
| #[test] | |
| fn decode() { | |
| let oid = ObjectIdentifier::from_der(EXAMPLE_OID_BYTES).unwrap(); | |
| assert_eq!(EXAMPLE_OID, oid); | |
| } | |
| #[test] | |
| fn encode() { | |
| let mut buffer = [0u8; 8]; | |
| assert_eq!( | |
| EXAMPLE_OID_BYTES, | |
| EXAMPLE_OID.encode_to_slice(&mut buffer).unwrap() | |
| ); | |
| } | |
| #[test] | |
| fn length() { | |
| // Ensure an infallible `From` conversion to `Any` will never panic | |
| assert!(ObjectIdentifier::MAX_SIZE <= Length::MAX.try_into().unwrap()); | |
| } | |
| } |