From 6de76919531dcf3514bc3b197dcff6c8c6f0ca1a Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 7 Nov 2025 16:37:16 -0700 Subject: [PATCH] der: have `PemReader` decode to `Cow::Owned` Adds an associated `CAN_READ_SLICE` boolean flag to the `Reader` trait. When false, `Cow` decodes the owned type rather than the borrow one. This makes it possible to use `Cow` with `PemReader`, where it will automatically decode the owned type. --- der/src/decode.rs | 14 ++++++++++---- der/src/reader.rs | 3 +++ der/src/reader/pem.rs | 2 ++ der/src/reader/slice.rs | 2 ++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/der/src/decode.rs b/der/src/decode.rs index 051e84a90..b003bec1f 100644 --- a/der/src/decode.rs +++ b/der/src/decode.rs @@ -212,14 +212,20 @@ where } #[cfg(feature = "alloc")] -impl<'a, T> DecodeValue<'a> for Cow<'a, T> +impl<'a, T, E> DecodeValue<'a> for Cow<'a, T> where T: ToOwned + ?Sized, - &'a T: DecodeValue<'a>, + &'a T: DecodeValue<'a, Error = E>, + T::Owned: for<'b> DecodeValue<'b, Error = E>, + E: From + 'static, { - type Error = <&'a T as DecodeValue<'a>>::Error; + type Error = E; fn decode_value>(reader: &mut R, header: Header) -> Result { - Ok(Cow::Borrowed(<&'a T>::decode_value(reader, header)?)) + if R::CAN_READ_SLICE { + <&'a T>::decode_value(reader, header).map(Cow::Borrowed) + } else { + T::Owned::decode_value(reader, header).map(Cow::Owned) + } } } diff --git a/der/src/reader.rs b/der/src/reader.rs index dc3c2e052..20eb919a5 100644 --- a/der/src/reader.rs +++ b/der/src/reader.rs @@ -20,6 +20,9 @@ use crate::length::indefinite::read_eoc; /// Reader trait which reads DER-encoded input. pub trait Reader<'r>: Clone { + /// Does this reader support the `read_slice` method? (i.e. can it borrow from his input?) + const CAN_READ_SLICE: bool; + /// Get the [`EncodingRules`] which should be applied when decoding the input. fn encoding_rules(&self) -> EncodingRules; diff --git a/der/src/reader/pem.rs b/der/src/reader/pem.rs index 3345326d3..f5ba41153 100644 --- a/der/src/reader/pem.rs +++ b/der/src/reader/pem.rs @@ -43,6 +43,8 @@ impl<'i> PemReader<'i> { #[cfg(feature = "pem")] impl<'i> Reader<'i> for PemReader<'i> { + const CAN_READ_SLICE: bool = false; + fn encoding_rules(&self) -> EncodingRules { self.encoding_rules } diff --git a/der/src/reader/slice.rs b/der/src/reader/slice.rs index 115155eac..cf769ba85 100644 --- a/der/src/reader/slice.rs +++ b/der/src/reader/slice.rs @@ -71,6 +71,8 @@ impl<'a> SliceReader<'a> { } impl<'a> Reader<'a> for SliceReader<'a> { + const CAN_READ_SLICE: bool = true; + fn encoding_rules(&self) -> EncodingRules { self.encoding_rules }