-
Notifications
You must be signed in to change notification settings - Fork 144
/
Copy pathreferenced.rs
158 lines (138 loc) · 4.07 KB
/
referenced.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//! 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.
/// The newly created object lifetime will be tied to the object owning the data.
///
/// 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<'a> {
/// The resulting type referencing back to Self
type Borrowed: 'a
where
Self: 'a;
/// Creates a new object referencing back to the self for storage
fn owned_to_ref(&'a self) -> Self::Borrowed;
}
/// A trait for cloning a referenced structure and getting owned objects
///
/// This is the pendant to [`OwnedToRef`].
///
/// This converts an object borrowing data to one that will copy the data over and
/// own the content.
pub trait RefToOwned<'a> {
/// The resulting type after obtaining ownership.
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<'a, T> OwnedToRef<'a> for Option<T>
where
T: OwnedToRef<'a> + 'a,
{
type Borrowed = Option<T::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<'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};
use alloc::boxed::Box;
impl<'a> RefToOwned<'a> for &'a [u8] {
type Owned = Box<[u8]>;
fn ref_to_owned(&self) -> Self::Owned {
Box::from(*self)
}
}
impl<'a> OwnedToRef<'a> for Box<[u8]> {
type Borrowed = &'a [u8];
fn owned_to_ref(&'a self) -> Self::Borrowed {
self.as_ref()
}
}
}