diff options
Diffstat (limited to 'vendor/der/src/asn1/oid.rs')
-rw-r--r-- | vendor/der/src/asn1/oid.rs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/vendor/der/src/asn1/oid.rs b/vendor/der/src/asn1/oid.rs new file mode 100644 index 000000000..8b287183d --- /dev/null +++ b/vendor/der/src/asn1/oid.rs @@ -0,0 +1,90 @@ +//! 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()); + } +} |