Skip to content

Commit 73e513e

Browse files
authored
der: improved internal ref types (#1921)
Changes `BytesRef` and `StringRef` from types with an explicit lifetime which act as newtypes for inner `&'a [u8]` and `&'a str` types to being newtypes for `[u8]` and `str`. This requires a very small amount of `unsafe` casting, but makes it possible to implement reference conversions entirely in terms of standard traits like `AsRef`, `Borrow`, `Deref`, and `ToOwned` as opposed to using our custom `RefToOwned` and OwnedToRef` traits. It makes it possible to use e.g. `Cow` as well. This is the first step towards moving the entire crate to this pattern and eliminating the `OwnedToRef` and `RefToOwned` raits, replacing them instead with the standard `AsRef`, `Borrow`, and `ToOwned` traits.
1 parent a3ea659 commit 73e513e

20 files changed

+270
-283
lines changed

der/src/asn1/any.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ pub struct AnyRef<'a> {
2929
tag: Tag,
3030

3131
/// Inner value encoded as bytes.
32-
value: BytesRef<'a>,
32+
value: &'a BytesRef,
3333
}
3434

3535
impl<'a> AnyRef<'a> {
3636
/// [`AnyRef`] representation of the ASN.1 `NULL` type.
3737
pub const NULL: Self = Self {
3838
tag: Tag::Null,
39-
value: BytesRef::EMPTY,
39+
value: BytesRef::new_unchecked(&[]),
4040
};
4141

4242
/// Create a new [`AnyRef`] from the provided [`Tag`] and DER bytes.
@@ -48,7 +48,7 @@ impl<'a> AnyRef<'a> {
4848
}
4949

5050
/// Infallible creation of an [`AnyRef`] from a [`BytesRef`].
51-
pub(crate) fn from_tag_and_value(tag: Tag, value: BytesRef<'a>) -> Self {
51+
pub(crate) fn from_tag_and_value(tag: Tag, value: &'a BytesRef) -> Self {
5252
Self { tag, value }
5353
}
5454

@@ -129,7 +129,7 @@ impl<'a> DecodeValue<'a> for AnyRef<'a> {
129129
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self, Error> {
130130
Ok(Self {
131131
tag: header.tag,
132-
value: BytesRef::decode_value(reader, header)?,
132+
value: <&'a BytesRef>::decode_value(reader, header)?,
133133
})
134134
}
135135
}
@@ -152,12 +152,12 @@ impl Tagged for AnyRef<'_> {
152152

153153
impl ValueOrd for AnyRef<'_> {
154154
fn value_cmp(&self, other: &Self) -> Result<Ordering, Error> {
155-
self.value.der_cmp(&other.value)
155+
self.value.der_cmp(other.value)
156156
}
157157
}
158158

159-
impl<'a> From<AnyRef<'a>> for BytesRef<'a> {
160-
fn from(any: AnyRef<'a>) -> BytesRef<'a> {
159+
impl<'a> From<AnyRef<'a>> for &'a BytesRef {
160+
fn from(any: AnyRef<'a>) -> &'a BytesRef {
161161
any.value
162162
}
163163
}
@@ -256,10 +256,10 @@ mod allocating {
256256
}
257257

258258
/// Create a new [`AnyRef`] from the provided [`Any`] owned tag and bytes.
259-
pub const fn to_ref(&self) -> AnyRef<'_> {
259+
pub fn to_ref(&self) -> AnyRef<'_> {
260260
AnyRef {
261261
tag: self.tag,
262-
value: self.value.to_ref(),
262+
value: self.value.as_ref(),
263263
}
264264
}
265265
}

der/src/asn1/bit_string.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub struct BitStringRef<'a> {
2626
bit_length: usize,
2727

2828
/// Bitstring represented as a slice of bytes.
29-
inner: BytesRef<'a>,
29+
inner: &'a BytesRef,
3030
}
3131

3232
impl<'a> BitStringRef<'a> {
@@ -145,7 +145,7 @@ impl<'a> DecodeValue<'a> for BitStringRef<'a> {
145145
};
146146

147147
let unused_bits = reader.read_byte()?;
148-
let inner = BytesRef::decode_value(reader, header)?;
148+
let inner = <&'a BytesRef>::decode_value(reader, header)?;
149149
Self::new(unused_bits, inner.as_slice())
150150
}
151151
}
@@ -164,7 +164,7 @@ impl EncodeValue for BitStringRef<'_> {
164164
impl ValueOrd for BitStringRef<'_> {
165165
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
166166
match self.unused_bits.cmp(&other.unused_bits) {
167-
Ordering::Equal => self.inner.der_cmp(&other.inner),
167+
Ordering::Equal => self.inner.der_cmp(other.inner),
168168
ordering => Ok(ordering),
169169
}
170170
}
@@ -233,13 +233,13 @@ impl<'a> arbitrary::Arbitrary<'a> for BitStringRef<'a> {
233233
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
234234
Self::new(
235235
u.int_in_range(0..=Self::MAX_UNUSED_BITS)?,
236-
BytesRef::arbitrary(u)?.as_slice(),
236+
<&'a BytesRef>::arbitrary(u)?.as_slice(),
237237
)
238238
.map_err(|_| arbitrary::Error::IncorrectFormat)
239239
}
240240

241241
fn size_hint(depth: usize) -> (usize, Option<usize>) {
242-
arbitrary::size_hint::and(u8::size_hint(depth), BytesRef::size_hint(depth))
242+
arbitrary::size_hint::and(u8::size_hint(depth), <&'a BytesRef>::size_hint(depth))
243243
}
244244
}
245245

@@ -421,13 +421,13 @@ mod allocating {
421421
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
422422
Self::new(
423423
u.int_in_range(0..=Self::MAX_UNUSED_BITS)?,
424-
BytesRef::arbitrary(u)?.as_slice(),
424+
<&'a BytesRef>::arbitrary(u)?.as_slice(),
425425
)
426426
.map_err(|_| arbitrary::Error::IncorrectFormat)
427427
}
428428

429429
fn size_hint(depth: usize) -> (usize, Option<usize>) {
430-
arbitrary::size_hint::and(u8::size_hint(depth), BytesRef::size_hint(depth))
430+
arbitrary::size_hint::and(u8::size_hint(depth), <&'a BytesRef>::size_hint(depth))
431431
}
432432
}
433433

der/src/asn1/general_string.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{BytesRef, DecodeValue, EncodeValue, FixedTag, Header, Length, Reader
44
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
55
pub struct GeneralStringRef<'a> {
66
/// Raw contents, unchecked
7-
inner: BytesRef<'a>,
7+
inner: &'a BytesRef,
88
}
99
impl<'a> GeneralStringRef<'a> {
1010
/// This is currently `&[u8]` internally, as `GeneralString` is not fully implemented yet
@@ -21,7 +21,7 @@ impl<'a> DecodeValue<'a> for GeneralStringRef<'a> {
2121

2222
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self, Self::Error> {
2323
Ok(Self {
24-
inner: BytesRef::decode_value(reader, header)?,
24+
inner: <&'a BytesRef>::decode_value(reader, header)?,
2525
})
2626
}
2727
}

der/src/asn1/ia5_string.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ macro_rules! impl_ia5_string {
3737
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
3838
pub struct Ia5StringRef<'a> {
3939
/// Inner value
40-
inner: StringRef<'a>,
40+
inner: &'a StringRef,
4141
}
4242

4343
impl<'a> Ia5StringRef<'a> {
@@ -57,15 +57,20 @@ impl<'a> Ia5StringRef<'a> {
5757
.map(|inner| Self { inner })
5858
.map_err(|_| Self::TAG.value_error().into())
5959
}
60+
61+
/// Borrow the inner `str`.
62+
pub fn as_str(&self) -> &'a str {
63+
self.inner.as_str()
64+
}
6065
}
6166

6267
impl_ia5_string!(Ia5StringRef<'a>, 'a);
6368

6469
impl<'a> Deref for Ia5StringRef<'a> {
65-
type Target = StringRef<'a>;
70+
type Target = StringRef;
6671

6772
fn deref(&self) -> &Self::Target {
68-
&self.inner
73+
self.inner
6974
}
7075
}
7176

@@ -77,7 +82,7 @@ impl<'a> From<&Ia5StringRef<'a>> for Ia5StringRef<'a> {
7782

7883
impl<'a> From<Ia5StringRef<'a>> for AnyRef<'a> {
7984
fn from(internationalized_string: Ia5StringRef<'a>) -> AnyRef<'a> {
80-
AnyRef::from_tag_and_value(Tag::Ia5String, internationalized_string.inner.into())
85+
AnyRef::from_tag_and_value(Tag::Ia5String, internationalized_string.inner.as_ref())
8186
}
8287
}
8388

@@ -92,7 +97,7 @@ mod allocation {
9297
asn1::AnyRef,
9398
referenced::{OwnedToRef, RefToOwned},
9499
};
95-
use alloc::string::String;
100+
use alloc::{borrow::ToOwned, string::String};
96101
use core::{fmt, ops::Deref};
97102

98103
/// ASN.1 `IA5String` type.
@@ -138,14 +143,15 @@ mod allocation {
138143

139144
impl<'a> From<Ia5StringRef<'a>> for Ia5String {
140145
fn from(ia5_string: Ia5StringRef<'a>) -> Ia5String {
141-
let inner = ia5_string.inner.into();
142-
Self { inner }
146+
Self {
147+
inner: ia5_string.inner.to_owned(),
148+
}
143149
}
144150
}
145151

146152
impl<'a> From<&'a Ia5String> for AnyRef<'a> {
147153
fn from(ia5_string: &'a Ia5String) -> AnyRef<'a> {
148-
AnyRef::from_tag_and_value(Tag::Ia5String, (&ia5_string.inner).into())
154+
AnyRef::from_tag_and_value(Tag::Ia5String, ia5_string.inner.as_ref())
149155
}
150156
}
151157

@@ -159,7 +165,7 @@ mod allocation {
159165
type Owned = Ia5String;
160166
fn ref_to_owned(&self) -> Self::Owned {
161167
Ia5String {
162-
inner: self.inner.ref_to_owned(),
168+
inner: self.inner.to_owned(),
163169
}
164170
}
165171
}
@@ -168,7 +174,7 @@ mod allocation {
168174
type Borrowed<'a> = Ia5StringRef<'a>;
169175
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
170176
Ia5StringRef {
171-
inner: self.inner.owned_to_ref(),
177+
inner: self.inner.as_ref(),
172178
}
173179
}
174180
}

der/src/asn1/integer/int.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ impl_encoding_traits!(i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128
102102
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
103103
pub struct IntRef<'a> {
104104
/// Inner value
105-
inner: BytesRef<'a>,
105+
inner: &'a BytesRef,
106106
}
107107

108108
impl<'a> IntRef<'a> {
@@ -137,7 +137,7 @@ impl<'a> DecodeValue<'a> for IntRef<'a> {
137137
type Error = Error;
138138

139139
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
140-
let bytes = BytesRef::decode_value(reader, header)?;
140+
let bytes = <&'a BytesRef>::decode_value(reader, header)?;
141141
validate_canonical(bytes.as_slice())?;
142142

143143
let result = Self::new(bytes.as_slice())?;
@@ -184,7 +184,7 @@ mod allocating {
184184
ord::OrdIsValueOrd,
185185
referenced::{OwnedToRef, RefToOwned},
186186
};
187-
use alloc::vec::Vec;
187+
use alloc::{borrow::ToOwned, vec::Vec};
188188

189189
/// Signed arbitrary precision ASN.1 `INTEGER` type.
190190
///
@@ -288,7 +288,7 @@ mod allocating {
288288
impl<'a> RefToOwned<'a> for IntRef<'a> {
289289
type Owned = Int;
290290
fn ref_to_owned(&self) -> Self::Owned {
291-
let inner = self.inner.ref_to_owned();
291+
let inner = self.inner.to_owned();
292292

293293
Int { inner }
294294
}
@@ -297,7 +297,7 @@ mod allocating {
297297
impl OwnedToRef for Int {
298298
type Borrowed<'a> = IntRef<'a>;
299299
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
300-
let inner = self.inner.owned_to_ref();
300+
let inner = self.inner.as_ref();
301301

302302
IntRef { inner }
303303
}

der/src/asn1/integer/uint.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl_encoding_traits!(u8, u16, u32, u64, u128);
8787
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
8888
pub struct UintRef<'a> {
8989
/// Inner value
90-
inner: BytesRef<'a>,
90+
inner: &'a BytesRef,
9191
}
9292

9393
impl<'a> UintRef<'a> {
@@ -122,7 +122,7 @@ impl<'a> DecodeValue<'a> for UintRef<'a> {
122122
type Error = Error;
123123

124124
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
125-
let bytes = BytesRef::decode_value(reader, header)?.as_slice();
125+
let bytes = <&'a BytesRef>::decode_value(reader, header)?.as_slice();
126126
let result = Self::new(decode_to_slice(bytes)?)?;
127127

128128
// Ensure we compute the same encoded length as the original any value.
@@ -170,6 +170,7 @@ mod allocating {
170170
ord::OrdIsValueOrd,
171171
referenced::{OwnedToRef, RefToOwned},
172172
};
173+
use alloc::borrow::ToOwned;
173174

174175
/// Unsigned arbitrary precision ASN.1 `INTEGER` type.
175176
///
@@ -260,7 +261,7 @@ mod allocating {
260261
impl<'a> RefToOwned<'a> for UintRef<'a> {
261262
type Owned = Uint;
262263
fn ref_to_owned(&self) -> Self::Owned {
263-
let inner = self.inner.ref_to_owned();
264+
let inner = self.inner.to_owned();
264265

265266
Uint { inner }
266267
}
@@ -269,7 +270,7 @@ mod allocating {
269270
impl OwnedToRef for Uint {
270271
type Borrowed<'a> = UintRef<'a>;
271272
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
272-
let inner = self.inner.owned_to_ref();
273+
let inner = self.inner.as_ref();
273274

274275
UintRef { inner }
275276
}

der/src/asn1/internal_macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ macro_rules! impl_string_type {
5151
type Error = $crate::Error;
5252

5353
fn decode_value<R: Reader<'__der>>(reader: &mut R, header: Header) -> $crate::Result<Self> {
54-
Self::new(BytesRef::decode_value(reader, header)?.as_slice())
54+
Self::new(<&'__der BytesRef>::decode_value(reader, header)?.as_slice())
5555
}
5656
}
5757

der/src/asn1/null.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl OrdIsValueOrd for Null {}
4141

4242
impl<'a> From<Null> for AnyRef<'a> {
4343
fn from(_: Null) -> AnyRef<'a> {
44-
AnyRef::from_tag_and_value(Tag::Null, BytesRef::default())
44+
AnyRef::from_tag_and_value(Tag::Null, BytesRef::EMPTY)
4545
}
4646
}
4747

der/src/asn1/octet_string.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::{
1313
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
1414
pub struct OctetStringRef<'a> {
1515
/// Inner value
16-
inner: BytesRef<'a>,
16+
inner: &'a BytesRef,
1717
}
1818

1919
impl<'a> OctetStringRef<'a> {
@@ -57,7 +57,7 @@ impl<'a> DecodeValue<'a> for OctetStringRef<'a> {
5757
type Error = Error;
5858

5959
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self, Error> {
60-
let inner = BytesRef::decode_value(reader, header)?;
60+
let inner = <&'a BytesRef>::decode_value(reader, header)?;
6161
Ok(Self { inner })
6262
}
6363
}
@@ -240,7 +240,7 @@ mod allocating {
240240
impl<'a> From<&'a OctetString> for OctetStringRef<'a> {
241241
fn from(octet_string: &'a OctetString) -> OctetStringRef<'a> {
242242
OctetStringRef {
243-
inner: octet_string.inner.owned_to_ref(),
243+
inner: octet_string.inner.as_ref(),
244244
}
245245
}
246246
}

0 commit comments

Comments
 (0)