Skip to content

Commit eddff1f

Browse files
committed
der: impl DecodeValue/EncodeValue/Tagged for Cow
Also includes a POC that the traits work with `OctetStringRef`
1 parent c916ce1 commit eddff1f

File tree

4 files changed

+78
-2
lines changed

4 files changed

+78
-2
lines changed

der/src/asn1/octet_string.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ impl<'a> DecodeValue<'a> for &'a OctetStringRef {
7373
}
7474
}
7575

76+
impl EncodeValue for OctetStringRef {
77+
fn value_len(&self) -> Result<Length, Error> {
78+
self.inner.value_len()
79+
}
80+
81+
fn encode_value(&self, writer: &mut impl Writer) -> Result<(), Error> {
82+
self.inner.encode_value(writer)
83+
}
84+
}
85+
7686
impl EncodeValue for &OctetStringRef {
7787
fn value_len(&self) -> Result<Length, Error> {
7888
self.inner.value_len()
@@ -383,6 +393,9 @@ mod tests {
383393
};
384394
use hex_literal::hex;
385395

396+
#[cfg(feature = "alloc")]
397+
use alloc::borrow::Cow;
398+
386399
#[test]
387400
fn octet_string_decode() {
388401
// PrintableString "hi"
@@ -405,6 +418,23 @@ mod tests {
405418
assert_eq!(AsRef::<str>::as_ref(&res), "hi");
406419
}
407420

421+
#[cfg(feature = "alloc")]
422+
#[test]
423+
fn cow_octet_string_decode_and_encode() {
424+
// PrintableString "hi"
425+
const EXAMPLE: &[u8] = &hex!(
426+
"040c" // primitive definite length OCTET STRING
427+
"48656c6c6f2c20776f726c64" // "Hello, world"
428+
);
429+
430+
let decoded = Cow::<OctetStringRef>::from_der(EXAMPLE).unwrap();
431+
assert_eq!(decoded.as_bytes(), b"Hello, world");
432+
433+
use crate::Encode;
434+
let encoded = decoded.to_der().unwrap();
435+
assert_eq!(EXAMPLE, encoded);
436+
}
437+
408438
#[test]
409439
#[cfg(all(feature = "alloc", feature = "ber"))]
410440
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: 19 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,20 @@ where
228232
}
229233
}
230234

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