Skip to content

Commit 6f39c12

Browse files
authored
der: remove SequenceRef lifetime; add constructor (#2224)
Changes `SequenceRef` into a `repr(transparent)` newtype for `BytesRef`, removing the lifetime and moving impls to `&SequenceRef`. This unfortunately necessitated a breaking change to `pkcs8`, which AFAICT is the only thing that currently uses it.
1 parent 700b2c6 commit 6f39c12

File tree

2 files changed

+33
-15
lines changed

2 files changed

+33
-15
lines changed

der/src/asn1/sequence.rs

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
//! `SEQUENCE`s to Rust structs.
33
44
use crate::{
5-
BytesRef, DecodeValue, EncodeValue, Error, FixedTag, Header, Length, Reader, Result, Tag,
6-
Writer,
5+
BytesRef, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader, Result,
6+
Tag, Writer,
77
};
88

99
#[cfg(feature = "alloc")]
@@ -12,7 +12,7 @@ use alloc::boxed::Box;
1212
/// Marker trait for ASN.1 `SEQUENCE`s.
1313
///
1414
/// This is mainly used for custom derive.
15-
pub trait Sequence<'a>: DecodeValue<'a> + EncodeValue {}
15+
pub trait Sequence<'a> {}
1616

1717
impl<'a, S> FixedTag for S
1818
where
@@ -28,35 +28,53 @@ impl<'a, T> Sequence<'a> for Box<T> where T: Sequence<'a> {}
2828
/// DER-encoded `SEQUENCE`.
2929
///
3030
/// This is a zero-copy reference type which borrows from the input data.
31-
pub struct SequenceRef<'a> {
31+
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
32+
#[repr(transparent)]
33+
pub struct SequenceRef {
3234
/// Body of the `SEQUENCE`.
33-
body: &'a BytesRef,
35+
body: BytesRef,
3436
}
3537

36-
impl<'a> SequenceRef<'a> {
38+
impl SequenceRef {
39+
/// Create a new ASN.1 `OCTET STRING` from a byte slice.
40+
pub fn new(slice: &[u8]) -> Result<&Self> {
41+
BytesRef::new(slice)
42+
.map(Self::from_bytes_ref)
43+
.map_err(|_| ErrorKind::Length { tag: Tag::Sequence }.into())
44+
}
45+
46+
/// Create a [`SequenceRef`] from a [`BytesRef`].
47+
///
48+
/// Implemented as an inherent method to keep [`BytesRef`] out of the public API.
49+
fn from_bytes_ref(bytes_ref: &BytesRef) -> &Self {
50+
// SAFETY: `Self` is a `repr(transparent)` newtype for `BytesRef`
51+
#[allow(unsafe_code)]
52+
unsafe {
53+
&*(bytes_ref.as_ptr() as *const Self)
54+
}
55+
}
56+
3757
/// Borrow the inner byte slice.
38-
pub fn as_bytes(&self) -> &'a [u8] {
58+
pub fn as_bytes(&self) -> &[u8] {
3959
self.body.as_slice()
4060
}
4161
}
4262

43-
impl AsRef<[u8]> for SequenceRef<'_> {
63+
impl AsRef<[u8]> for SequenceRef {
4464
fn as_ref(&self) -> &[u8] {
4565
self.as_bytes()
4666
}
4767
}
4868

49-
impl<'a> DecodeValue<'a> for SequenceRef<'a> {
69+
impl<'a> DecodeValue<'a> for &'a SequenceRef {
5070
type Error = Error;
5171

5272
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
53-
Ok(Self {
54-
body: <&'a BytesRef>::decode_value(reader, header)?,
55-
})
73+
<&'a BytesRef>::decode_value(reader, header).map(SequenceRef::from_bytes_ref)
5674
}
5775
}
5876

59-
impl EncodeValue for SequenceRef<'_> {
77+
impl EncodeValue for SequenceRef {
6078
fn value_len(&self) -> Result<Length> {
6179
Ok(self.body.len())
6280
}
@@ -66,4 +84,4 @@ impl EncodeValue for SequenceRef<'_> {
6684
}
6785
}
6886

69-
impl<'a> Sequence<'a> for SequenceRef<'a> {}
87+
impl<'a> Sequence<'a> for &'a SequenceRef {}

pkcs8/src/private_key_info.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ where
203203
let private_key = Key::decode(reader)?;
204204

205205
let _attributes =
206-
reader.context_specific::<SequenceRef<'_>>(ATTRIBUTES_TAG, TagMode::Implicit)?;
206+
reader.context_specific::<&SequenceRef>(ATTRIBUTES_TAG, TagMode::Implicit)?;
207207

208208
let public_key = reader.context_specific::<PubKey>(PUBLIC_KEY_TAG, TagMode::Implicit)?;
209209

0 commit comments

Comments
 (0)