Skip to content

Commit 2a06eca

Browse files
committed
der: remove lifetime from OctetStringRef
Following the pattern of #1921, removes the lifetime from the struct, instead changing `OctetStringRef` to a proper reference type to be used as `&OctetStringRef`. This makes it possible to `impl Borrow<OctetStringRef> for OctetString` and `impl ToOwned for OctetStringRef`, so they can work with `Cow`.
1 parent 07cc006 commit 2a06eca

File tree

18 files changed

+147
-99
lines changed

18 files changed

+147
-99
lines changed

cms/src/attr.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
//! Attribute-related types
2+
//!
23
use alloc::{boxed::Box, vec};
4+
use core::borrow::Borrow;
35
use der::{
46
DecodeValue, EncodeValue, FixedTag, Length, Tag,
57
asn1::{OctetString, OctetStringRef},
6-
referenced::OwnedToRef,
78
};
8-
99
use x509_cert::time::Time;
1010

1111
use crate::signed_data::SignerInfo;
@@ -50,8 +50,8 @@ impl MessageDigest {
5050

5151
/// Return an [`OctetStringRef`] pointing to the underlying data
5252
#[inline]
53-
pub fn as_octet_string_ref<'a>(&'a self) -> OctetStringRef<'a> {
54-
self.0.owned_to_ref()
53+
pub fn as_octet_string_ref(&self) -> &OctetStringRef {
54+
self.0.borrow()
5555
}
5656
}
5757

cms/src/timestamped_data.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub struct TimeStampedData<'a> {
4444
#[asn1(optional = "true")]
4545
pub meta_data: Option<MetaData>,
4646
#[asn1(optional = "true")]
47-
pub content: Option<OctetStringRef<'a>>,
47+
pub content: Option<&'a OctetStringRef>,
4848
pub temporal_evidence: Evidence,
4949
}
5050

cms/tests/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ fn test_create_password_recipient_info() {
946946
.to_der()
947947
.unwrap();
948948
let iv = Iv::<cbc::Decryptor<Aes128>>::try_from(
949-
OctetStringRef::from_der(algorithm_params_der.as_slice())
949+
<&OctetStringRef>::from_der(algorithm_params_der.as_slice())
950950
.unwrap()
951951
.as_bytes(),
952952
)

cms/tests/tests_from_pkcs7_crate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ fn cms_decode_signed_der() {
123123
sd.encap_content_info
124124
.econtent
125125
.unwrap()
126-
.decode_as::<OctetStringRef>()
126+
.decode_as::<&OctetStringRef>()
127127
.unwrap()
128128
.as_bytes()
129129
.len(),

der/src/asn1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub use self::{
4444
ia5_string::Ia5StringRef,
4545
integer::{int::IntRef, uint::UintRef},
4646
null::Null,
47-
octet_string::OctetStringRef,
47+
octet_string::{OctetStringRef, OctetStringRef2},
4848
printable_string::PrintableStringRef,
4949
private::{Private, PrivateRef},
5050
sequence::{Sequence, SequenceRef},

der/src/asn1/octet_string.rs

Lines changed: 101 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,43 @@ use crate::{
55
Tag, Writer, asn1::AnyRef, ord::OrdIsValueOrd,
66
};
77

8+
// TODO(tarcieri): custom derive hack until the logic is updated to support `&'a` reference types
9+
#[doc(hidden)]
10+
pub type OctetStringRef2<'a> = &'a OctetStringRef;
11+
812
/// ASN.1 `OCTET STRING` type: borrowed form.
913
///
1014
/// Octet strings represent contiguous sequences of octets, a.k.a. bytes.
1115
///
1216
/// This is a zero-copy reference type which borrows from the input data.
13-
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
14-
pub struct OctetStringRef<'a> {
17+
#[derive(Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
18+
#[repr(transparent)]
19+
pub struct OctetStringRef {
1520
/// Inner value
16-
inner: &'a BytesRef,
21+
inner: BytesRef,
1722
}
1823

19-
impl<'a> OctetStringRef<'a> {
24+
impl OctetStringRef {
2025
/// Create a new ASN.1 `OCTET STRING` from a byte slice.
21-
pub fn new(slice: &'a [u8]) -> Result<Self, Error> {
26+
pub fn new(slice: &[u8]) -> Result<&Self, Error> {
2227
BytesRef::new(slice)
23-
.map(|inner| Self { inner })
28+
.map(Self::from_bytes_ref)
2429
.map_err(|_| ErrorKind::Length { tag: Self::TAG }.into())
2530
}
2631

32+
/// Create an [`OctetStringRef`] from a [`BytesRef`].
33+
///
34+
/// Implemented as an inherent method to keep [`BytesRef`] out of the public API.
35+
fn from_bytes_ref(bytes_ref: &BytesRef) -> &Self {
36+
// SAFETY: `Self` is a `repr(transparent)` newtype for `BytesRef`
37+
#[allow(unsafe_code)]
38+
unsafe {
39+
&*(bytes_ref.as_ptr() as *const Self)
40+
}
41+
}
42+
2743
/// Borrow the inner byte slice.
28-
pub fn as_bytes(&self) -> &'a [u8] {
44+
pub fn as_bytes(&self) -> &[u8] {
2945
self.inner.as_slice()
3046
}
3147

@@ -40,29 +56,28 @@ impl<'a> OctetStringRef<'a> {
4056
}
4157

4258
/// Parse `T` from this `OCTET STRING`'s contents.
43-
pub fn decode_into<T: Decode<'a>>(&self) -> Result<T, T::Error> {
59+
pub fn decode_into<'a, T: Decode<'a>>(&'a self) -> Result<T, T::Error> {
4460
Decode::from_der(self.as_bytes())
4561
}
4662
}
4763

48-
impl_any_conversions!(OctetStringRef<'a>, 'a);
64+
//impl_any_conversions!(OctetStringRef<'a>, 'a);
4965

50-
impl AsRef<[u8]> for OctetStringRef<'_> {
66+
impl AsRef<[u8]> for OctetStringRef {
5167
fn as_ref(&self) -> &[u8] {
5268
self.as_bytes()
5369
}
5470
}
5571

56-
impl<'a> DecodeValue<'a> for OctetStringRef<'a> {
72+
impl<'a> DecodeValue<'a> for &'a OctetStringRef {
5773
type Error = Error;
5874

5975
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self, Error> {
60-
let inner = <&'a BytesRef>::decode_value(reader, header)?;
61-
Ok(Self { inner })
76+
<&'a BytesRef>::decode_value(reader, header).map(OctetStringRef::from_bytes_ref)
6277
}
6378
}
6479

65-
impl EncodeValue for OctetStringRef<'_> {
80+
impl EncodeValue for &OctetStringRef {
6681
fn value_len(&self) -> Result<Length, Error> {
6782
self.inner.value_len()
6883
}
@@ -72,59 +87,56 @@ impl EncodeValue for OctetStringRef<'_> {
7287
}
7388
}
7489

75-
impl FixedTag for OctetStringRef<'_> {
90+
impl FixedTag for OctetStringRef {
7691
const TAG: Tag = Tag::OctetString;
7792
}
78-
79-
impl OrdIsValueOrd for OctetStringRef<'_> {}
80-
81-
impl<'a> From<&OctetStringRef<'a>> for OctetStringRef<'a> {
82-
fn from(value: &OctetStringRef<'a>) -> OctetStringRef<'a> {
83-
*value
84-
}
93+
impl FixedTag for &OctetStringRef {
94+
const TAG: Tag = Tag::OctetString;
8595
}
8696

87-
impl<'a> From<OctetStringRef<'a>> for AnyRef<'a> {
88-
fn from(octet_string: OctetStringRef<'a>) -> AnyRef<'a> {
89-
AnyRef::from_tag_and_value(Tag::OctetString, octet_string.inner)
97+
impl OrdIsValueOrd for &OctetStringRef {}
98+
99+
impl<'a> From<&'a OctetStringRef> for AnyRef<'a> {
100+
fn from(octet_string: &'a OctetStringRef) -> AnyRef<'a> {
101+
AnyRef::from_tag_and_value(Tag::OctetString, &octet_string.inner)
90102
}
91103
}
92104

93-
impl<'a> From<OctetStringRef<'a>> for &'a [u8] {
94-
fn from(octet_string: OctetStringRef<'a>) -> &'a [u8] {
105+
impl<'a> From<&'a OctetStringRef> for &'a [u8] {
106+
fn from(octet_string: &'a OctetStringRef) -> &'a [u8] {
95107
octet_string.as_bytes()
96108
}
97109
}
98110

99-
impl<'a> TryFrom<&'a [u8]> for OctetStringRef<'a> {
111+
impl<'a> TryFrom<&'a [u8]> for &'a OctetStringRef {
100112
type Error = Error;
101113

102114
fn try_from(byte_slice: &'a [u8]) -> Result<Self, Error> {
103115
OctetStringRef::new(byte_slice)
104116
}
105117
}
106118

107-
/// Hack for simplifying the custom derive use case.
108-
impl<'a> TryFrom<&&'a [u8]> for OctetStringRef<'a> {
119+
// TODO(tarcieri): hack to make derive tests pass. Get rid of this!
120+
impl<'a> TryFrom<&&'a [u8]> for &'a OctetStringRef {
109121
type Error = Error;
110122

111123
fn try_from(byte_slice: &&'a [u8]) -> Result<Self, Error> {
112124
OctetStringRef::new(byte_slice)
113125
}
114126
}
115127

116-
impl<'a, const N: usize> TryFrom<&'a [u8; N]> for OctetStringRef<'a> {
128+
impl<'a, const N: usize> TryFrom<&'a [u8; N]> for &'a OctetStringRef {
117129
type Error = Error;
118130

119131
fn try_from(byte_slice: &'a [u8; N]) -> Result<Self, Error> {
120132
OctetStringRef::new(byte_slice)
121133
}
122134
}
123135

124-
impl<'a, const N: usize> TryFrom<OctetStringRef<'a>> for [u8; N] {
136+
impl<'a, const N: usize> TryFrom<&'a OctetStringRef> for [u8; N] {
125137
type Error = Error;
126138

127-
fn try_from(octet_string: OctetStringRef<'a>) -> Result<Self, Self::Error> {
139+
fn try_from(octet_string: &'a OctetStringRef) -> Result<Self, Self::Error> {
128140
octet_string
129141
.as_bytes()
130142
.try_into()
@@ -133,10 +145,10 @@ impl<'a, const N: usize> TryFrom<OctetStringRef<'a>> for [u8; N] {
133145
}
134146

135147
#[cfg(feature = "heapless")]
136-
impl<'a, const N: usize> TryFrom<OctetStringRef<'a>> for heapless::Vec<u8, N> {
148+
impl<const N: usize> TryFrom<&OctetStringRef> for heapless::Vec<u8, N> {
137149
type Error = Error;
138150

139-
fn try_from(octet_string: OctetStringRef<'a>) -> Result<Self, Self::Error> {
151+
fn try_from(octet_string: &OctetStringRef) -> Result<Self, Self::Error> {
140152
octet_string
141153
.as_bytes()
142154
.try_into()
@@ -145,7 +157,7 @@ impl<'a, const N: usize> TryFrom<OctetStringRef<'a>> for heapless::Vec<u8, N> {
145157
}
146158

147159
#[cfg(feature = "heapless")]
148-
impl<'a, const N: usize> TryFrom<&'a heapless::Vec<u8, N>> for OctetStringRef<'a> {
160+
impl<'a, const N: usize> TryFrom<&'a heapless::Vec<u8, N>> for &'a OctetStringRef {
149161
type Error = Error;
150162

151163
fn try_from(byte_vec: &'a heapless::Vec<u8, N>) -> Result<Self, Error> {
@@ -159,8 +171,12 @@ pub use self::allocating::OctetString;
159171
#[cfg(feature = "alloc")]
160172
mod allocating {
161173
use super::*;
162-
use crate::{BytesOwned, referenced::*};
163-
use alloc::{borrow::Cow, boxed::Box, vec::Vec};
174+
use crate::BytesOwned;
175+
use alloc::{
176+
borrow::{Borrow, Cow, ToOwned},
177+
boxed::Box,
178+
vec::Vec,
179+
};
164180

165181
/// ASN.1 `OCTET STRING` type: owned form.
166182
///
@@ -214,6 +230,12 @@ mod allocating {
214230
}
215231
}
216232

233+
impl Borrow<OctetStringRef> for OctetString {
234+
fn borrow(&self) -> &OctetStringRef {
235+
OctetStringRef::from_bytes_ref(self.inner.as_ref())
236+
}
237+
}
238+
217239
impl<'a> DecodeValue<'a> for OctetString {
218240
type Error = Error;
219241

@@ -237,40 +259,30 @@ mod allocating {
237259
const TAG: Tag = Tag::OctetString;
238260
}
239261

240-
impl<'a> From<&'a OctetString> for OctetStringRef<'a> {
241-
fn from(octet_string: &'a OctetString) -> OctetStringRef<'a> {
242-
OctetStringRef {
243-
inner: octet_string.inner.as_ref(),
244-
}
245-
}
246-
}
247-
248262
impl OrdIsValueOrd for OctetString {}
249263

250-
impl<'a> RefToOwned<'a> for OctetStringRef<'a> {
251-
type Owned = OctetString;
252-
fn ref_to_owned(&self) -> Self::Owned {
253-
OctetString {
254-
inner: self.inner.into(),
255-
}
264+
impl<'a> From<&'a OctetString> for &'a OctetStringRef {
265+
fn from(octet_string: &'a OctetString) -> &'a OctetStringRef {
266+
OctetStringRef::from_bytes_ref(octet_string.inner.as_ref())
256267
}
257268
}
258269

259-
impl OwnedToRef for OctetString {
260-
type Borrowed<'a> = OctetStringRef<'a>;
261-
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
262-
self.into()
270+
impl From<&OctetStringRef> for OctetString {
271+
fn from(octet_string_ref: &OctetStringRef) -> OctetString {
272+
Self {
273+
inner: octet_string_ref.inner.to_owned(),
274+
}
263275
}
264276
}
265277

266-
impl From<OctetStringRef<'_>> for Vec<u8> {
267-
fn from(octet_string: OctetStringRef<'_>) -> Vec<u8> {
278+
impl From<&OctetStringRef> for Vec<u8> {
279+
fn from(octet_string: &OctetStringRef) -> Vec<u8> {
268280
Vec::from(octet_string.as_bytes())
269281
}
270282
}
271283

272284
/// Hack for simplifying the custom derive use case.
273-
impl<'a> TryFrom<&'a Vec<u8>> for OctetStringRef<'a> {
285+
impl<'a> TryFrom<&'a Vec<u8>> for &'a OctetStringRef {
274286
type Error = Error;
275287

276288
fn try_from(byte_vec: &'a Vec<u8>) -> Result<Self, Error> {
@@ -284,18 +296,26 @@ mod allocating {
284296
}
285297
}
286298

287-
impl<'a> TryFrom<&'a Cow<'a, [u8]>> for OctetStringRef<'a> {
299+
impl ToOwned for OctetStringRef {
300+
type Owned = OctetString;
301+
302+
fn to_owned(&self) -> OctetString {
303+
self.into()
304+
}
305+
}
306+
307+
impl<'a> TryFrom<&'a Cow<'a, [u8]>> for &'a OctetStringRef {
288308
type Error = Error;
289309

290310
fn try_from(byte_slice: &'a Cow<'a, [u8]>) -> Result<Self, Error> {
291311
OctetStringRef::new(byte_slice)
292312
}
293313
}
294314

295-
impl<'a> TryFrom<OctetStringRef<'a>> for Cow<'a, [u8]> {
315+
impl<'a> TryFrom<&'a OctetStringRef> for Cow<'a, [u8]> {
296316
type Error = Error;
297317

298-
fn try_from(octet_string: OctetStringRef<'a>) -> Result<Self, Self::Error> {
318+
fn try_from(octet_string: &'a OctetStringRef) -> Result<Self, Self::Error> {
299319
Ok(Cow::Borrowed(octet_string.as_bytes()))
300320
}
301321
}
@@ -345,8 +365,8 @@ mod bytes {
345365
const TAG: Tag = Tag::OctetString;
346366
}
347367

348-
impl From<OctetStringRef<'_>> for Bytes {
349-
fn from(octet_string: OctetStringRef<'_>) -> Bytes {
368+
impl From<&OctetStringRef> for Bytes {
369+
fn from(octet_string: &OctetStringRef) -> Bytes {
350370
Vec::from(octet_string).into()
351371
}
352372
}
@@ -361,7 +381,23 @@ mod bytes {
361381
#[cfg(test)]
362382
#[allow(clippy::unwrap_used)]
363383
mod tests {
364-
use crate::asn1::{OctetStringRef, PrintableStringRef};
384+
use crate::{
385+
Decode,
386+
asn1::{OctetStringRef, PrintableStringRef},
387+
};
388+
use hex_literal::hex;
389+
390+
#[test]
391+
fn octet_string_decode() {
392+
// PrintableString "hi"
393+
const EXAMPLE: &[u8] = &hex!(
394+
"040c" // primitive definite length OCTET STRING
395+
"48656c6c6f2c20776f726c64" // "Hello, world"
396+
);
397+
398+
let decoded = <&OctetStringRef>::from_der(EXAMPLE).unwrap();
399+
assert_eq!(decoded.as_bytes(), b"Hello, world");
400+
}
365401

366402
#[test]
367403
fn octet_string_decode_into() {

0 commit comments

Comments
 (0)