Skip to content

Commit c8ff2bd

Browse files
authored
der: impl DecodeValue/EncodeValue/Tagged for Cow (#2093)
Also includes a POC that the traits work with `OctetStringRef`
1 parent c916ce1 commit c8ff2bd

File tree

4 files changed

+68
-2
lines changed

4 files changed

+68
-2
lines changed

der/src/asn1/octet_string.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,9 @@ mod tests {
383383
};
384384
use hex_literal::hex;
385385

386+
#[cfg(feature = "alloc")]
387+
use {crate::Encode, alloc::borrow::Cow};
388+
386389
#[test]
387390
fn octet_string_decode() {
388391
// PrintableString "hi"
@@ -405,6 +408,22 @@ mod tests {
405408
assert_eq!(AsRef::<str>::as_ref(&res), "hi");
406409
}
407410

411+
#[cfg(feature = "alloc")]
412+
#[test]
413+
fn cow_octet_string_decode_and_encode() {
414+
// PrintableString "hi"
415+
const EXAMPLE: &[u8] = &hex!(
416+
"040c" // primitive definite length OCTET STRING
417+
"48656c6c6f2c20776f726c64" // "Hello, world"
418+
);
419+
420+
let decoded = Cow::<OctetStringRef>::from_der(EXAMPLE).unwrap();
421+
assert_eq!(decoded.as_bytes(), b"Hello, world");
422+
423+
let encoded = decoded.to_der().unwrap();
424+
assert_eq!(EXAMPLE, encoded);
425+
}
426+
408427
#[test]
409428
#[cfg(all(feature = "alloc", feature = "ber"))]
410429
fn decode_ber_primitive_definite() {

der/src/decode.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ use crate::{PemReader, pem::PemLabel};
1111
use crate::{ErrorKind, Length, Tag};
1212

1313
#[cfg(feature = "alloc")]
14-
use alloc::boxed::Box;
14+
use alloc::{
15+
borrow::{Cow, ToOwned},
16+
boxed::Box,
17+
};
1518

1619
#[cfg(feature = "ber")]
1720
use crate::EncodingRules;
@@ -207,3 +210,16 @@ where
207210
Ok(Box::new(T::decode_value(reader, header)?))
208211
}
209212
}
213+
214+
#[cfg(feature = "alloc")]
215+
impl<'a, T> DecodeValue<'a> for Cow<'a, T>
216+
where
217+
T: ToOwned + ?Sized,
218+
&'a T: DecodeValue<'a>,
219+
{
220+
type Error = <&'a T as DecodeValue<'a>>::Error;
221+
222+
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self, Self::Error> {
223+
Ok(Cow::Borrowed(<&'a T>::decode_value(reader, header)?))
224+
}
225+
}

der/src/encode.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ use crate::{Header, Length, Result, SliceWriter, Tagged, Writer};
44
use core::marker::PhantomData;
55

66
#[cfg(feature = "alloc")]
7-
use {alloc::boxed::Box, alloc::vec::Vec};
7+
use alloc::{
8+
borrow::{Cow, ToOwned},
9+
boxed::Box,
10+
vec::Vec,
11+
};
812

913
#[cfg(feature = "pem")]
1014
use {
@@ -228,6 +232,21 @@ where
228232
}
229233
}
230234

235+
#[cfg(feature = "alloc")]
236+
impl<T> EncodeValue for Cow<'_, T>
237+
where
238+
T: ToOwned + ?Sized,
239+
for<'a> &'a T: EncodeValue,
240+
{
241+
fn value_len(&self) -> Result<Length> {
242+
self.as_ref().value_len()
243+
}
244+
245+
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
246+
self.as_ref().encode_value(writer)
247+
}
248+
}
249+
231250
/// Encodes value only (without tag + length) to a slice.
232251
pub(crate) fn encode_value_to_slice<'a, T>(buf: &'a mut [u8], value: &T) -> Result<&'a [u8]>
233252
where

der/src/tag.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ pub use self::{class::Class, mode::TagMode, number::TagNumber};
1010
use crate::{Decode, DerOrd, Encode, Error, ErrorKind, Length, Reader, Result, Writer};
1111
use core::{cmp::Ordering, fmt};
1212

13+
#[cfg(feature = "alloc")]
14+
use alloc::borrow::{Cow, ToOwned};
15+
1316
/// Indicator bit for constructed form encoding (i.e. vs primitive form)
1417
const CONSTRUCTED_FLAG: u8 = 0b100000;
1518

@@ -30,6 +33,15 @@ pub trait FixedTag {
3033
const TAG: Tag;
3134
}
3235

36+
#[cfg(feature = "alloc")]
37+
impl<'a, T> FixedTag for Cow<'a, T>
38+
where
39+
T: ToOwned + ?Sized,
40+
&'a T: FixedTag,
41+
{
42+
const TAG: Tag = <&'a T>::TAG;
43+
}
44+
3345
/// Types which have an ASN.1 [`Tag`].
3446
///
3547
/// ## Example

0 commit comments

Comments
 (0)