Skip to content

wip: add der::Cow enum #1778

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions der/src/asn1/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,9 @@ mod allocating {
}
}

impl OwnedToRef for Any {
type Borrowed<'a> = AnyRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
impl<'a> OwnedToRef<'a> for Any {
type Borrowed = AnyRef<'a>;
fn owned_to_ref(&'a self) -> Self::Borrowed {
self.into()
}
}
Expand Down
9 changes: 5 additions & 4 deletions der/src/asn1/bit_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,10 +441,11 @@ mod allocating {
}
}

impl OwnedToRef for BitString {
type Borrowed<'a> = BitStringRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
self.into()
impl<'a> OwnedToRef<'a> for BitString {
type Borrowed = BitStringRef<'a>;
fn owned_to_ref(&'a self) -> Self::Borrowed {
// Ensured to parse successfully in constructor
BitStringRef::new(self.unused_bits, &self.inner).expect("invalid BIT STRING")
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions der/src/asn1/ia5_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,9 @@ mod allocation {
}
}

impl OwnedToRef for Ia5String {
type Borrowed<'a> = Ia5StringRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
impl<'a> OwnedToRef<'a> for Ia5String {
type Borrowed = Ia5StringRef<'a>;
fn owned_to_ref(&'a self) -> Self::Borrowed {
Ia5StringRef {
inner: self.inner.owned_to_ref(),
}
Expand Down
6 changes: 3 additions & 3 deletions der/src/asn1/integer/int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,9 @@ mod allocating {
}
}

impl OwnedToRef for Int {
type Borrowed<'a> = IntRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
impl<'a> OwnedToRef<'a> for Int {
type Borrowed = IntRef<'a>;
fn owned_to_ref(&'a self) -> Self::Borrowed {
let inner = self.inner.owned_to_ref();

IntRef { inner }
Expand Down
6 changes: 3 additions & 3 deletions der/src/asn1/integer/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,9 @@ mod allocating {
}
}

impl OwnedToRef for Uint {
type Borrowed<'a> = UintRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
impl<'a> OwnedToRef<'a> for Uint {
type Borrowed = UintRef<'a>;
fn owned_to_ref(&'a self) -> Self::Borrowed {
let inner = self.inner.owned_to_ref();

UintRef { inner }
Expand Down
8 changes: 4 additions & 4 deletions der/src/asn1/octet_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::{
BytesRef, Decode, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader,
Tag, Writer, asn1::AnyRef, ord::OrdIsValueOrd,
Tag, Writer, asn1::AnyRef, ord::OrdIsValueOrd, referenced::RefToOwned,
};

/// ASN.1 `OCTET STRING` type: borrowed form.
Expand Down Expand Up @@ -254,9 +254,9 @@ mod allocating {
}
}

impl OwnedToRef for OctetString {
type Borrowed<'a> = OctetStringRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
impl<'a> OwnedToRef<'a> for OctetString {
type Borrowed = OctetStringRef<'a>;
fn owned_to_ref(&'a self) -> Self::Borrowed {
self.into()
}
}
Expand Down
6 changes: 3 additions & 3 deletions der/src/asn1/printable_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,9 @@ mod allocation {
}
}

impl OwnedToRef for PrintableString {
type Borrowed<'a> = PrintableStringRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
impl<'a> OwnedToRef<'a> for PrintableString {
type Borrowed = PrintableStringRef<'a>;
fn owned_to_ref(&'a self) -> Self::Borrowed {
PrintableStringRef {
inner: self.inner.owned_to_ref(),
}
Expand Down
6 changes: 3 additions & 3 deletions der/src/asn1/teletex_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ mod allocation {
}
}

impl OwnedToRef for TeletexString {
type Borrowed<'a> = TeletexStringRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
impl<'a> OwnedToRef<'a> for TeletexString {
type Borrowed = TeletexStringRef<'a>;
fn owned_to_ref(&'a self) -> Self::Borrowed {
TeletexStringRef {
inner: self.inner.owned_to_ref(),
}
Expand Down
6 changes: 3 additions & 3 deletions der/src/bytes_owned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ impl From<StrRef<'_>> for BytesOwned {
}
}

impl OwnedToRef for BytesOwned {
type Borrowed<'a> = BytesRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
impl<'a> OwnedToRef<'a> for BytesOwned {
type Borrowed = BytesRef<'a>;
fn owned_to_ref(&'a self) -> Self::Borrowed {
BytesRef {
length: self.length,
inner: self.inner.as_ref(),
Expand Down
106 changes: 91 additions & 15 deletions der/src/referenced.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! A module for working with referenced data.

use crate::FixedTag;

/// A trait for borrowing data from an owned struct
///
/// This converts an object owning the data to one that will borrowing the content.
Expand All @@ -8,14 +10,14 @@
/// This is similar to [`alloc::borrow::Borrow`] or [`core::convert::AsRef`] but this returns
/// an owned structure that references directly the backing slices instead of borrowing
/// the whole structure.
pub trait OwnedToRef {
pub trait OwnedToRef<'a> {
/// The resulting type referencing back to Self
type Borrowed<'a>
type Borrowed: 'a
where
Self: 'a;

/// Creates a new object referencing back to the self for storage
fn owned_to_ref(&self) -> Self::Borrowed<'_>;
fn owned_to_ref(&'a self) -> Self::Borrowed;
}

/// A trait for cloning a referenced structure and getting owned objects
Expand All @@ -26,39 +28,113 @@ pub trait OwnedToRef {
/// own the content.
pub trait RefToOwned<'a> {
/// The resulting type after obtaining ownership.
type Owned: OwnedToRef<Borrowed<'a> = Self>
type Owned: OwnedToRef<'a, Borrowed = Self>
where
Self: 'a;

/// Creates a new object taking ownership of the data
fn ref_to_owned(&self) -> Self::Owned;
}

impl<T> OwnedToRef for Option<T>
impl<'a, T> OwnedToRef<'a> for Option<T>
where
T: OwnedToRef,
T: OwnedToRef<'a> + 'a,
{
type Borrowed<'a>
= Option<T::Borrowed<'a>>
where
T: 'a;
type Borrowed = Option<T::Borrowed>;

fn owned_to_ref(&self) -> Self::Borrowed<'_> {
fn owned_to_ref(&'a self) -> Self::Borrowed {
self.as_ref().map(|o| o.owned_to_ref())
}
}

impl<'a, T> RefToOwned<'a> for Option<T>
where
T: RefToOwned<'a> + 'a,
T::Owned: OwnedToRef,
T::Owned: OwnedToRef<'a>,
{
type Owned = Option<T::Owned>;
fn ref_to_owned(&self) -> Self::Owned {
self.as_ref().map(|o| o.ref_to_owned())
}
}

/// der crate version of `Cow`
pub enum DerCow<'a, B>
where
B: RefToOwned<'a> + ?Sized,
{
/// referenced, for example `OctetStringRef`
Borrowed(&'a B),
/// allocated, for example `OctetString`
Owned(<B as RefToOwned<'a>>::Owned),
}

impl<'a, B> core::fmt::Debug for DerCow<'a, B>
where
B: RefToOwned<'a> + ?Sized + core::fmt::Debug,
<B as RefToOwned<'a>>::Owned: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Borrowed(arg0) => f.debug_tuple("Borrowed").field(arg0).finish(),
Self::Owned(arg0) => f.debug_tuple("Owned").field(arg0).finish(),
}
}
}

impl<'a, B> Clone for DerCow<'a, B>
where
B: RefToOwned<'a> + ?Sized,
<B as RefToOwned<'a>>::Owned: Clone,
{
fn clone(&self) -> Self {
match self {
Self::Borrowed(arg0) => Self::Borrowed(arg0),
Self::Owned(arg0) => Self::Owned(arg0.clone()),
}
}
}

impl<'a, B> FixedTag for DerCow<'a, B>
where
B: RefToOwned<'a> + ?Sized + FixedTag,
{
const TAG: crate::Tag = B::TAG;
}

impl<'a, B> PartialEq for DerCow<'a, B>
where
B: RefToOwned<'a> + Sized + PartialEq,
<B as RefToOwned<'a>>::Owned: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Borrowed(l0), Self::Borrowed(r0)) => l0 == r0,
(Self::Owned(l0), Self::Owned(r0)) => l0 == r0,
(Self::Owned(l0), Self::Borrowed(r0)) => {
let l1 = l0.owned_to_ref();
*r0 == &l1
}
_ => false,
}
}
}

// impl<'a, B> Deref for DerCow<'a, B>
// where
// B: RefToOwned<'a> + ?Sized,
// <B as RefToOwned<'a>>::Owned: OwnedToRef,
// {
// type Target = B;

// fn deref(&self) -> &B {
// match *self {
// Self::Borrowed(borrowed) => borrowed,
// Self::Owned(owned) => owned.owned_to_ref(),
// }
// }
// }

#[cfg(feature = "alloc")]
mod allocating {
use super::{OwnedToRef, RefToOwned};
Expand All @@ -72,10 +148,10 @@ mod allocating {
}
}

impl OwnedToRef for Box<[u8]> {
type Borrowed<'a> = &'a [u8];
impl<'a> OwnedToRef<'a> for Box<[u8]> {
type Borrowed = &'a [u8];

fn owned_to_ref(&self) -> Self::Borrowed<'_> {
fn owned_to_ref(&'a self) -> Self::Borrowed {
self.as_ref()
}
}
Expand Down
6 changes: 3 additions & 3 deletions der/src/str_owned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ impl From<StrRef<'_>> for StrOwned {
}
}

impl OwnedToRef for StrOwned {
type Borrowed<'a> = StrRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
impl<'a> OwnedToRef<'a> for StrOwned {
type Borrowed = StrRef<'a>;
fn owned_to_ref(&'a self) -> Self::Borrowed {
StrRef {
length: self.length,
inner: self.inner.as_ref(),
Expand Down
31 changes: 31 additions & 0 deletions x509-cert/src/certificate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use crate::{ext, name::Name, serial_number::SerialNumber, time::Validity};
use alloc::vec::Vec;
use const_oid::AssociatedOid;
use core::{cmp::Ordering, fmt::Debug};
use der::asn1::BitStringRef;
use der::referenced::DerCow;
use der::{Decode, Enumerated, ErrorKind, Sequence, Tag, ValueOrd, asn1::BitString};

#[cfg(feature = "pem")]
Expand Down Expand Up @@ -168,6 +170,35 @@ pub struct TbsCertificateInner<P: Profile = Rfc5280> {
pub(crate) extensions: Option<ext::Extensions>,
}

#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)]
#[allow(missing_docs)]
pub struct TbsCertificateInnerCow<'a, P: Profile = Rfc5280> {
/// The certificate version.
///
/// Note that this value defaults to Version 1 per the RFC. However,
/// fields such as `issuer_unique_id`, `subject_unique_id` and `extensions`
/// require later versions. Care should be taken in order to ensure
/// standards compliance.
#[asn1(context_specific = "0", default = "Default::default")]
pub(crate) version: Version,

pub(crate) serial_number: SerialNumber<P>,
pub(crate) signature: AlgorithmIdentifier,
pub(crate) issuer: Name,
pub(crate) validity: Validity<P>,
pub(crate) subject: Name,
pub(crate) subject_public_key_info: SubjectPublicKeyInfo,

#[asn1(context_specific = "1", tag_mode = "IMPLICIT", optional = "true")]
pub(crate) issuer_unique_id: Option<DerCow<BitStringRef<'a>>>,

#[asn1(context_specific = "2", tag_mode = "IMPLICIT", optional = "true")]
pub(crate) subject_unique_id: Option<BitString>,

#[asn1(context_specific = "3", tag_mode = "EXPLICIT", optional = "true")]
pub(crate) extensions: Option<ext::Extensions>,
}

impl<P: Profile> TbsCertificateInner<P> {
/// [`Version`] of this certificate (v1/v2/v3).
pub fn version(&self) -> Version {
Expand Down
Loading