Skip to content

Commit 2359ca5

Browse files
committed
[WIP] 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 8c60e19 commit 2359ca5

File tree

2 files changed

+101
-72
lines changed

2 files changed

+101
-72
lines changed

der/src/asn1/octet_string.rs

Lines changed: 96 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,34 @@ use crate::{
1010
/// Octet strings represent contiguous sequences of octets, a.k.a. bytes.
1111
///
1212
/// 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> {
13+
#[derive(Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
14+
#[repr(transparent)]
15+
pub struct OctetStringRef {
1516
/// Inner value
16-
inner: &'a BytesRef,
17+
inner: BytesRef,
1718
}
1819

19-
impl<'a> OctetStringRef<'a> {
20+
impl OctetStringRef {
2021
/// Create a new ASN.1 `OCTET STRING` from a byte slice.
21-
pub fn new(slice: &'a [u8]) -> Result<Self, Error> {
22+
pub fn new<'a>(slice: &'a [u8]) -> Result<&'a Self, Error> {
2223
BytesRef::new(slice)
23-
.map(|inner| Self { inner })
24+
.map(Self::from_bytes_ref)
2425
.map_err(|_| ErrorKind::Length { tag: Self::TAG }.into())
2526
}
2627

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

@@ -40,29 +52,28 @@ impl<'a> OctetStringRef<'a> {
4052
}
4153

4254
/// Parse `T` from this `OCTET STRING`'s contents.
43-
pub fn decode_into<T: Decode<'a>>(&self) -> Result<T, T::Error> {
55+
pub fn decode_into<'a, T: Decode<'a>>(&'a self) -> Result<T, T::Error> {
4456
Decode::from_der(self.as_bytes())
4557
}
4658
}
4759

48-
impl_any_conversions!(OctetStringRef<'a>, 'a);
60+
//impl_any_conversions!(OctetStringRef<'a>, 'a);
4961

50-
impl AsRef<[u8]> for OctetStringRef<'_> {
62+
impl AsRef<[u8]> for OctetStringRef {
5163
fn as_ref(&self) -> &[u8] {
5264
self.as_bytes()
5365
}
5466
}
5567

56-
impl<'a> DecodeValue<'a> for OctetStringRef<'a> {
68+
impl<'a> DecodeValue<'a> for &'a OctetStringRef {
5769
type Error = Error;
5870

5971
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 })
72+
<&'a BytesRef>::decode_value(reader, header).map(OctetStringRef::from_bytes_ref)
6273
}
6374
}
6475

65-
impl EncodeValue for OctetStringRef<'_> {
76+
impl EncodeValue for OctetStringRef {
6677
fn value_len(&self) -> Result<Length, Error> {
6778
self.inner.value_len()
6879
}
@@ -72,59 +83,47 @@ impl EncodeValue for OctetStringRef<'_> {
7283
}
7384
}
7485

75-
impl FixedTag for OctetStringRef<'_> {
86+
impl FixedTag for OctetStringRef {
7687
const TAG: Tag = Tag::OctetString;
7788
}
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-
}
89+
impl FixedTag for &OctetStringRef {
90+
const TAG: Tag = Tag::OctetString;
8591
}
8692

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)
93+
impl OrdIsValueOrd for OctetStringRef {}
94+
95+
impl<'a> From<&'a OctetStringRef> for AnyRef<'a> {
96+
fn from(octet_string: &'a OctetStringRef) -> AnyRef<'a> {
97+
AnyRef::from_tag_and_value(Tag::OctetString, &octet_string.inner)
9098
}
9199
}
92100

93-
impl<'a> From<OctetStringRef<'a>> for &'a [u8] {
94-
fn from(octet_string: OctetStringRef<'a>) -> &'a [u8] {
101+
impl<'a> From<&'a OctetStringRef> for &'a [u8] {
102+
fn from(octet_string: &'a OctetStringRef) -> &'a [u8] {
95103
octet_string.as_bytes()
96104
}
97105
}
98106

99-
impl<'a> TryFrom<&'a [u8]> for OctetStringRef<'a> {
107+
impl<'a> TryFrom<&'a [u8]> for &'a OctetStringRef {
100108
type Error = Error;
101109

102110
fn try_from(byte_slice: &'a [u8]) -> Result<Self, Error> {
103111
OctetStringRef::new(byte_slice)
104112
}
105113
}
106114

107-
/// Hack for simplifying the custom derive use case.
108-
impl<'a> TryFrom<&&'a [u8]> for OctetStringRef<'a> {
109-
type Error = Error;
110-
111-
fn try_from(byte_slice: &&'a [u8]) -> Result<Self, Error> {
112-
OctetStringRef::new(byte_slice)
113-
}
114-
}
115-
116-
impl<'a, const N: usize> TryFrom<&'a [u8; N]> for OctetStringRef<'a> {
115+
impl<'a, const N: usize> TryFrom<&'a [u8; N]> for &'a OctetStringRef {
117116
type Error = Error;
118117

119118
fn try_from(byte_slice: &'a [u8; N]) -> Result<Self, Error> {
120119
OctetStringRef::new(byte_slice)
121120
}
122121
}
123122

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

127-
fn try_from(octet_string: OctetStringRef<'a>) -> Result<Self, Self::Error> {
126+
fn try_from(octet_string: &'a OctetStringRef) -> Result<Self, Self::Error> {
128127
octet_string
129128
.as_bytes()
130129
.try_into()
@@ -133,10 +132,10 @@ impl<'a, const N: usize> TryFrom<OctetStringRef<'a>> for [u8; N] {
133132
}
134133

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

139-
fn try_from(octet_string: OctetStringRef<'a>) -> Result<Self, Self::Error> {
138+
fn try_from(octet_string: &OctetStringRef) -> Result<Self, Self::Error> {
140139
octet_string
141140
.as_bytes()
142141
.try_into()
@@ -145,7 +144,7 @@ impl<'a, const N: usize> TryFrom<OctetStringRef<'a>> for heapless::Vec<u8, N> {
145144
}
146145

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

151150
fn try_from(byte_vec: &'a heapless::Vec<u8, N>) -> Result<Self, Error> {
@@ -159,8 +158,13 @@ pub use self::allocating::OctetString;
159158
#[cfg(feature = "alloc")]
160159
mod allocating {
161160
use super::*;
162-
use crate::{BytesOwned, referenced::*};
163-
use alloc::{borrow::Cow, boxed::Box, vec::Vec};
161+
use crate::BytesOwned;
162+
use alloc::{
163+
borrow::{Borrow, Cow},
164+
boxed::Box,
165+
vec::Vec,
166+
};
167+
use std::prelude::rust_2015::ToOwned;
164168

165169
/// ASN.1 `OCTET STRING` type: owned form.
166170
///
@@ -214,6 +218,12 @@ mod allocating {
214218
}
215219
}
216220

221+
impl Borrow<OctetStringRef> for OctetString {
222+
fn borrow(&self) -> &OctetStringRef {
223+
OctetStringRef::from_bytes_ref(self.inner.as_ref())
224+
}
225+
}
226+
217227
impl<'a> DecodeValue<'a> for OctetString {
218228
type Error = Error;
219229

@@ -237,40 +247,30 @@ mod allocating {
237247
const TAG: Tag = Tag::OctetString;
238248
}
239249

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-
248250
impl OrdIsValueOrd for OctetString {}
249251

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-
}
252+
impl<'a> From<&'a OctetString> for &'a OctetStringRef {
253+
fn from(octet_string: &'a OctetString) -> &'a OctetStringRef {
254+
OctetStringRef::from_bytes_ref(octet_string.inner.as_ref())
256255
}
257256
}
258257

259-
impl OwnedToRef for OctetString {
260-
type Borrowed<'a> = OctetStringRef<'a>;
261-
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
262-
self.into()
258+
impl From<&OctetStringRef> for OctetString {
259+
fn from(octet_string_ref: &OctetStringRef) -> OctetString {
260+
Self {
261+
inner: octet_string_ref.inner.to_owned(),
262+
}
263263
}
264264
}
265265

266-
impl From<OctetStringRef<'_>> for Vec<u8> {
267-
fn from(octet_string: OctetStringRef<'_>) -> Vec<u8> {
266+
impl From<&OctetStringRef> for Vec<u8> {
267+
fn from(octet_string: &OctetStringRef) -> Vec<u8> {
268268
Vec::from(octet_string.as_bytes())
269269
}
270270
}
271271

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

276276
fn try_from(byte_vec: &'a Vec<u8>) -> Result<Self, Error> {
@@ -284,18 +284,26 @@ mod allocating {
284284
}
285285
}
286286

287-
impl<'a> TryFrom<&'a Cow<'a, [u8]>> for OctetStringRef<'a> {
287+
impl ToOwned for OctetStringRef {
288+
type Owned = OctetString;
289+
290+
fn to_owned(&self) -> OctetString {
291+
self.into()
292+
}
293+
}
294+
295+
impl<'a> TryFrom<&'a Cow<'a, [u8]>> for &'a OctetStringRef {
288296
type Error = Error;
289297

290298
fn try_from(byte_slice: &'a Cow<'a, [u8]>) -> Result<Self, Error> {
291299
OctetStringRef::new(byte_slice)
292300
}
293301
}
294302

295-
impl<'a> TryFrom<OctetStringRef<'a>> for Cow<'a, [u8]> {
303+
impl<'a> TryFrom<&'a OctetStringRef> for Cow<'a, [u8]> {
296304
type Error = Error;
297305

298-
fn try_from(octet_string: OctetStringRef<'a>) -> Result<Self, Self::Error> {
306+
fn try_from(octet_string: &'a OctetStringRef) -> Result<Self, Self::Error> {
299307
Ok(Cow::Borrowed(octet_string.as_bytes()))
300308
}
301309
}
@@ -345,8 +353,8 @@ mod bytes {
345353
const TAG: Tag = Tag::OctetString;
346354
}
347355

348-
impl From<OctetStringRef<'_>> for Bytes {
349-
fn from(octet_string: OctetStringRef<'_>) -> Bytes {
356+
impl From<&OctetStringRef> for Bytes {
357+
fn from(octet_string: &OctetStringRef) -> Bytes {
350358
Vec::from(octet_string).into()
351359
}
352360
}
@@ -361,7 +369,23 @@ mod bytes {
361369
#[cfg(test)]
362370
#[allow(clippy::unwrap_used)]
363371
mod tests {
364-
use crate::asn1::{OctetStringRef, PrintableStringRef};
372+
use crate::{
373+
Decode,
374+
asn1::{OctetStringRef, PrintableStringRef},
375+
};
376+
use hex_literal::hex;
377+
378+
#[test]
379+
fn octet_string_decode() {
380+
// PrintableString "hi"
381+
const EXAMPLE: &[u8] = &hex!(
382+
"040c" // primitive definite length OCTET STRING
383+
"48656c6c6f2c20776f726c64" // "Hello, world"
384+
);
385+
386+
let decoded = <&OctetStringRef>::from_der(EXAMPLE).unwrap();
387+
assert_eq!(decoded.as_bytes(), b"Hello, world");
388+
}
365389

366390
#[test]
367391
fn octet_string_decode_into() {

der/src/bytes.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ impl BytesRef {
3131
}
3232
}
3333

34+
/// Get a pointer to this [`BytesRef`].
35+
pub(crate) const fn as_ptr(&self) -> *const BytesRef {
36+
self as *const BytesRef
37+
}
38+
3439
/// Borrow the inner byte slice
3540
pub const fn as_slice(&self) -> &[u8] {
3641
&self.0

0 commit comments

Comments
 (0)