Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 46 additions & 34 deletions der/src/asn1/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
use core::cmp::Ordering;

#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use crate::Bytes;

#[cfg(feature = "oid")]
use crate::asn1::ObjectIdentifier;
Expand Down Expand Up @@ -94,11 +94,6 @@ impl<'a> AnyRef<'a> {
self.try_into()
}

/// Attempt to decode an ASN.1 `IA5String`.
pub fn ia5_string(self) -> Result<Ia5StringRef<'a>> {
self.try_into()
}

/// Attempt to decode an ASN.1 `OCTET STRING`.
pub fn octet_string(self) -> Result<OctetStringRef<'a>> {
self.try_into()
Expand All @@ -123,21 +118,6 @@ impl<'a> AnyRef<'a> {
}
}

/// Attempt to decode an ASN.1 `PrintableString`.
pub fn printable_string(self) -> Result<PrintableStringRef<'a>> {
self.try_into()
}

/// Attempt to decode an ASN.1 `TeletexString`.
pub fn teletex_string(self) -> Result<TeletexStringRef<'a>> {
self.try_into()
}

/// Attempt to decode an ASN.1 `VideotexString`.
pub fn videotex_string(self) -> Result<VideotexStringRef<'a>> {
self.try_into()
}

/// Attempt to decode this value an ASN.1 `SEQUENCE`, creating a new
/// nested reader and calling the provided argument with it.
pub fn sequence<F, T>(self, f: F) -> Result<T>
Expand All @@ -154,11 +134,6 @@ impl<'a> AnyRef<'a> {
pub fn utc_time(self) -> Result<UtcTime> {
self.try_into()
}

/// Attempt to decode an ASN.1 `UTF8String`.
pub fn utf8_string(self) -> Result<Utf8StringRef<'a>> {
self.try_into()
}
}

impl<'a> Choice<'a> for AnyRef<'a> {
Expand Down Expand Up @@ -194,6 +169,13 @@ impl Tagged for AnyRef<'_> {
}
}

#[cfg(feature = "alloc")]
impl ValueOrd for Any {
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
self.value.der_cmp(&other.value)
}
}

impl ValueOrd for AnyRef<'_> {
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
self.value.der_cmp(&other.value)
Expand Down Expand Up @@ -226,19 +208,35 @@ pub struct Any {
tag: Tag,

/// Inner value encoded as bytes.
value: Vec<u8>,
value: Bytes,
}

#[cfg(feature = "alloc")]
impl Any {
/// Create a new [`Any`] from the provided [`Tag`] and DER bytes.
pub fn new(tag: Tag, bytes: impl Into<Vec<u8>>) -> Result<Self> {
let value = bytes.into();
pub fn new(tag: Tag, bytes: &[u8]) -> Result<Self> {
let value = Bytes::new(bytes)?;

// Ensure the tag and value are a valid `AnyRef`.
AnyRef::new(tag, &value)?;
AnyRef::new(tag, value.as_slice())?;
Ok(Self { tag, value })
}

/// Attempt to decode this [`Any`] type into the inner value.
pub fn decode_into<'a, T>(&'a self) -> Result<T>
where
T: DecodeValue<'a> + FixedTag,
{
self.tag.assert_eq(T::TAG)?;
let header = Header {
tag: self.tag,
length: self.value.len(),
};

let mut decoder = SliceReader::new(self.value.as_slice())?;
let result = T::decode_value(&mut decoder, header)?;
decoder.finish(result)
}
}

#[cfg(feature = "alloc")]
Expand All @@ -253,26 +251,26 @@ impl<'a> Decode<'a> for Any {
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Self> {
let header = Header::decode(reader)?;
let value = reader.read_vec(header.length)?;
Self::new(header.tag, value)
Self::new(header.tag, &value)
}
}

#[cfg(feature = "alloc")]
impl EncodeValue for Any {
fn value_len(&self) -> Result<Length> {
self.value.len().try_into()
Ok(self.value.len())
}

fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
writer.write(&self.value)
writer.write(self.value.as_slice())
}
}

#[cfg(feature = "alloc")]
impl<'a> From<&'a Any> for AnyRef<'a> {
fn from(any: &'a Any) -> AnyRef<'a> {
// Ensured to parse successfully in constructor
AnyRef::new(any.tag, &any.value).expect("invalid ANY")
AnyRef::new(any.tag, any.value.as_slice()).expect("invalid ANY")
}
}

Expand All @@ -282,3 +280,17 @@ impl Tagged for Any {
self.tag
}
}

#[cfg(feature = "alloc")]
impl<'a, T> From<T> for Any
where
T: Into<AnyRef<'a>>,
{
fn from(input: T) -> Any {
let anyref: AnyRef<'a> = input.into();
Self {
tag: anyref.tag(),
value: Bytes::from(anyref.value),
}
}
}
12 changes: 12 additions & 0 deletions der/src/asn1/ia5_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use crate::{
};
use core::{fmt, ops::Deref, str};

#[cfg(feature = "alloc")]
use crate::asn1::Any;

/// ASN.1 `IA5String` type.
///
/// Supports the [International Alphabet No. 5 (IA5)] character encoding, i.e.
Expand Down Expand Up @@ -99,6 +102,15 @@ impl<'a> TryFrom<AnyRef<'a>> for Ia5StringRef<'a> {
}
}

#[cfg(feature = "alloc")]
impl<'a> TryFrom<&'a Any> for Ia5StringRef<'a> {
type Error = Error;

fn try_from(any: &'a Any) -> Result<Ia5StringRef<'a>> {
any.decode_into()
}
}

impl<'a> From<Ia5StringRef<'a>> for AnyRef<'a> {
fn from(printable_string: Ia5StringRef<'a>) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::Ia5String, printable_string.inner.into())
Expand Down
12 changes: 12 additions & 0 deletions der/src/asn1/printable_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use crate::{
};
use core::{fmt, ops::Deref, str};

#[cfg(feature = "alloc")]
use crate::asn1::Any;

/// ASN.1 `PrintableString` type.
///
/// Supports a subset the ASCII character set (described below).
Expand Down Expand Up @@ -133,6 +136,15 @@ impl<'a> TryFrom<AnyRef<'a>> for PrintableStringRef<'a> {
}
}

#[cfg(feature = "alloc")]
impl<'a> TryFrom<&'a Any> for PrintableStringRef<'a> {
type Error = Error;

fn try_from(any: &'a Any) -> Result<PrintableStringRef<'a>> {
any.decode_into()
}
}

impl<'a> From<PrintableStringRef<'a>> for AnyRef<'a> {
fn from(printable_string: PrintableStringRef<'a>) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::PrintableString, printable_string.inner.into())
Expand Down
12 changes: 12 additions & 0 deletions der/src/asn1/teletex_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use crate::{
};
use core::{fmt, ops::Deref, str};

#[cfg(feature = "alloc")]
use crate::asn1::Any;

/// ASN.1 `TeletexString` type.
///
/// Supports a subset the ASCII character set (described below).
Expand Down Expand Up @@ -103,6 +106,15 @@ impl<'a> TryFrom<AnyRef<'a>> for TeletexStringRef<'a> {
}
}

#[cfg(feature = "alloc")]
impl<'a> TryFrom<&'a Any> for TeletexStringRef<'a> {
type Error = Error;

fn try_from(any: &'a Any) -> Result<TeletexStringRef<'a>> {
any.decode_into()
}
}

impl<'a> From<TeletexStringRef<'a>> for AnyRef<'a> {
fn from(teletex_string: TeletexStringRef<'a>) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::TeletexString, teletex_string.inner.into())
Expand Down
18 changes: 15 additions & 3 deletions der/src/asn1/utf8_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use crate::{
use core::{fmt, ops::Deref, str};

#[cfg(feature = "alloc")]
use alloc::{borrow::ToOwned, string::String};
use {
crate::asn1::Any,
alloc::{borrow::ToOwned, string::String},
};

/// ASN.1 `UTF8String` type.
///
Expand Down Expand Up @@ -95,9 +98,18 @@ impl<'a> TryFrom<AnyRef<'a>> for Utf8StringRef<'a> {
}
}

#[cfg(feature = "alloc")]
impl<'a> TryFrom<&'a Any> for Utf8StringRef<'a> {
type Error = Error;

fn try_from(any: &'a Any) -> Result<Utf8StringRef<'a>> {
any.decode_into()
}
}

impl<'a> From<Utf8StringRef<'a>> for AnyRef<'a> {
fn from(printable_string: Utf8StringRef<'a>) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::Utf8String, printable_string.inner.into())
fn from(utf_string: Utf8StringRef<'a>) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::Utf8String, utf_string.inner.into())
}
}

Expand Down
12 changes: 12 additions & 0 deletions der/src/asn1/videotex_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use crate::{
};
use core::{fmt, ops::Deref, str};

#[cfg(feature = "alloc")]
use crate::asn1::Any;

/// ASN.1 `VideotexString` type.
///
/// Supports a subset the ASCII character set (described below).
Expand Down Expand Up @@ -102,6 +105,15 @@ impl<'a> TryFrom<AnyRef<'a>> for VideotexStringRef<'a> {
}
}

#[cfg(feature = "alloc")]
impl<'a> TryFrom<&'a Any> for VideotexStringRef<'a> {
type Error = Error;

fn try_from(any: &'a Any) -> Result<VideotexStringRef<'a>> {
any.decode_into()
}
}

impl<'a> From<VideotexStringRef<'a>> for AnyRef<'a> {
fn from(printable_string: VideotexStringRef<'a>) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::VideotexString, printable_string.inner.into())
Expand Down
4 changes: 2 additions & 2 deletions der/src/byte_slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ use core::cmp::Ordering;
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub(crate) struct ByteSlice<'a> {
/// Precomputed `Length` (avoids possible panicking conversions)
length: Length,
pub length: Length,

/// Inner value
inner: &'a [u8],
pub inner: &'a [u8],
}

impl<'a> ByteSlice<'a> {
Expand Down
Loading