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
19 changes: 19 additions & 0 deletions der/src/asn1/octet_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,9 @@ mod tests {
};
use hex_literal::hex;

#[cfg(feature = "alloc")]
use {crate::Encode, alloc::borrow::Cow};

#[test]
fn octet_string_decode() {
// PrintableString "hi"
Expand All @@ -405,6 +408,22 @@ mod tests {
assert_eq!(AsRef::<str>::as_ref(&res), "hi");
}

#[cfg(feature = "alloc")]
#[test]
fn cow_octet_string_decode_and_encode() {
// PrintableString "hi"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a PrintableString "hi"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

D'oh!

const EXAMPLE: &[u8] = &hex!(
"040c" // primitive definite length OCTET STRING
"48656c6c6f2c20776f726c64" // "Hello, world"
);

let decoded = Cow::<OctetStringRef>::from_der(EXAMPLE).unwrap();
assert_eq!(decoded.as_bytes(), b"Hello, world");

let encoded = decoded.to_der().unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! So it "just works" 😄

But the sad part is Cow<BitStringRef> and "alloc"-gated Cow.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not much that can be done about an alloc-gated Cow. You can make the type generic so you can swap out Cow<'a, OctetStringRef> for &'a OctetStringRef>.

I can potentially make BitStringRef work, though it will be somewhat annoying.

assert_eq!(EXAMPLE, encoded);
}

#[test]
#[cfg(all(feature = "alloc", feature = "ber"))]
fn decode_ber_primitive_definite() {
Expand Down
18 changes: 17 additions & 1 deletion der/src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use crate::{PemReader, pem::PemLabel};
use crate::{ErrorKind, Length, Tag};

#[cfg(feature = "alloc")]
use alloc::boxed::Box;
use alloc::{
borrow::{Cow, ToOwned},
boxed::Box,
};

#[cfg(feature = "ber")]
use crate::EncodingRules;
Expand Down Expand Up @@ -207,3 +210,16 @@ where
Ok(Box::new(T::decode_value(reader, header)?))
}
}

#[cfg(feature = "alloc")]
impl<'a, T> DecodeValue<'a> for Cow<'a, T>
where
T: ToOwned + ?Sized,
&'a T: DecodeValue<'a>,
{
type Error = <&'a T as DecodeValue<'a>>::Error;

fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self, Self::Error> {
Ok(Cow::Borrowed(<&'a T>::decode_value(reader, header)?))
}
}
21 changes: 20 additions & 1 deletion der/src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ use crate::{Header, Length, Result, SliceWriter, Tagged, Writer};
use core::marker::PhantomData;

#[cfg(feature = "alloc")]
use {alloc::boxed::Box, alloc::vec::Vec};
use alloc::{
borrow::{Cow, ToOwned},
boxed::Box,
vec::Vec,
};

#[cfg(feature = "pem")]
use {
Expand Down Expand Up @@ -228,6 +232,21 @@ where
}
}

#[cfg(feature = "alloc")]
impl<T> EncodeValue for Cow<'_, T>
where
T: ToOwned + ?Sized,
for<'a> &'a T: EncodeValue,
{
fn value_len(&self) -> Result<Length> {
self.as_ref().value_len()
}

fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
self.as_ref().encode_value(writer)
}
}

/// Encodes value only (without tag + length) to a slice.
pub(crate) fn encode_value_to_slice<'a, T>(buf: &'a mut [u8], value: &T) -> Result<&'a [u8]>
where
Expand Down
12 changes: 12 additions & 0 deletions der/src/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ pub use self::{class::Class, mode::TagMode, number::TagNumber};
use crate::{Decode, DerOrd, Encode, Error, ErrorKind, Length, Reader, Result, Writer};
use core::{cmp::Ordering, fmt};

#[cfg(feature = "alloc")]
use alloc::borrow::{Cow, ToOwned};

/// Indicator bit for constructed form encoding (i.e. vs primitive form)
const CONSTRUCTED_FLAG: u8 = 0b100000;

Expand All @@ -30,6 +33,15 @@ pub trait FixedTag {
const TAG: Tag;
}

#[cfg(feature = "alloc")]
impl<'a, T> FixedTag for Cow<'a, T>
where
T: ToOwned + ?Sized,
&'a T: FixedTag,
{
const TAG: Tag = <&'a T>::TAG;
}

/// Types which have an ASN.1 [`Tag`].
///
/// ## Example
Expand Down