diff --git a/der/src/asn1/bit_string.rs b/der/src/asn1/bit_string.rs index 146541bf6..c182edab8 100644 --- a/der/src/asn1/bit_string.rs +++ b/der/src/asn1/bit_string.rs @@ -193,6 +193,24 @@ impl<'a> TryFrom<&&'a [u8]> for BitStringRef<'a> { } } +impl<'a, const N: usize> TryFrom<&'a [u8; N]> for BitStringRef<'a> { + type Error = Error; + + fn try_from(bytes: &'a [u8; N]) -> Result> { + BitStringRef::from_bytes(bytes) + } +} + +impl<'a, const N: usize> TryFrom> for [u8; N] { + type Error = Error; + + fn try_from(bit_string: BitStringRef<'a>) -> Result { + let bytes: &[u8] = TryFrom::try_from(bit_string)?; + + bytes.try_into().map_err(|_| Tag::BitString.length_error()) + } +} + impl<'a> TryFrom> for &'a [u8] { type Error = Error; diff --git a/der/src/asn1/octet_string.rs b/der/src/asn1/octet_string.rs index e4bf0aff2..76b2d1756 100644 --- a/der/src/asn1/octet_string.rs +++ b/der/src/asn1/octet_string.rs @@ -113,6 +113,25 @@ impl<'a> TryFrom<&&'a [u8]> for OctetStringRef<'a> { } } +impl<'a, const N: usize> TryFrom<&'a [u8; N]> for OctetStringRef<'a> { + type Error = Error; + + fn try_from(byte_slice: &'a [u8; N]) -> Result { + OctetStringRef::new(byte_slice) + } +} + +impl<'a, const N: usize> TryFrom> for [u8; N] { + type Error = Error; + + fn try_from(octet_string: OctetStringRef<'a>) -> Result { + octet_string + .as_bytes() + .try_into() + .map_err(|_| Tag::OctetString.length_error()) + } +} + #[cfg(feature = "alloc")] pub use self::allocating::OctetString; diff --git a/der/tests/derive.rs b/der/tests/derive.rs index 0624ba21f..3c9abbb52 100644 --- a/der/tests/derive.rs +++ b/der/tests/derive.rs @@ -528,7 +528,7 @@ mod sequence { pub owned_optional_implicit_bytes: Option>, #[asn1( - type = "OCTET STRING", + type = "BIT STRING", context_specific = "6", optional = "true", tag_mode = "EXPLICIT" @@ -568,6 +568,85 @@ mod sequence { assert_eq!(obj, obj_decoded); } + #[derive(Sequence, Default, Eq, PartialEq, Debug)] + #[asn1(tag_mode = "IMPLICIT")] + pub struct TypeCheckArraysSequenceFieldAttributeCombinations { + #[asn1(type = "OCTET STRING", deref = "true")] + pub array_bytes: [u8; 2], + + #[asn1(type = "BIT STRING", deref = "true")] + pub array_bits: [u8; 2], + + #[asn1(type = "OCTET STRING", context_specific = "0", deref = "true")] + pub array_implicit_bytes: [u8; 2], + + #[asn1(type = "BIT STRING", context_specific = "1", deref = "true")] + pub array_implicit_bits: [u8; 2], + + #[asn1( + type = "OCTET STRING", + context_specific = "2", + tag_mode = "EXPLICIT", + deref = "true" + )] + pub array_explicit_bytes: [u8; 2], + + #[asn1( + type = "BIT STRING", + context_specific = "3", + tag_mode = "EXPLICIT", + deref = "true" + )] + pub array_explicit_bits: [u8; 2], + + #[asn1(type = "BIT STRING", context_specific = "4", optional = "true")] + pub array_optional_implicit_bits: Option<[u8; 2]>, + + #[asn1(type = "OCTET STRING", context_specific = "5", optional = "true")] + pub array_optional_implicit_bytes: Option<[u8; 2]>, + + #[asn1( + type = "BIT STRING", + context_specific = "6", + optional = "true", + tag_mode = "EXPLICIT" + )] + pub array_optional_explicit_bits: Option<[u8; 2]>, + + #[asn1( + type = "OCTET STRING", + context_specific = "7", + optional = "true", + tag_mode = "EXPLICIT" + )] + pub array_optional_explicit_bytes: Option<[u8; 2]>, + } + + #[test] + fn type_combinations_arrays_instance() { + let obj = TypeCheckArraysSequenceFieldAttributeCombinations { + array_bytes: [0xAA, 0xBB], + array_bits: [0xCC, 0xDD], + + array_implicit_bytes: [0, 1], + array_implicit_bits: [2, 3], + + array_explicit_bytes: [4, 5], + array_explicit_bits: [6, 7], + + array_optional_implicit_bits: Some([8, 9]), + array_optional_implicit_bytes: Some([10, 11]), + + array_optional_explicit_bits: Some([12, 13]), + array_optional_explicit_bytes: Some([14, 15]), + }; + + let der_encoded = obj.to_der().unwrap(); + let obj_decoded = + TypeCheckArraysSequenceFieldAttributeCombinations::from_der(&der_encoded).unwrap(); + assert_eq!(obj, obj_decoded); + } + #[derive(Sequence)] #[asn1(error = CustomError)] pub struct TypeWithCustomError {