src/instance.rs

branch
dev
changeset 59
9226980e45a7
child 75
e9f4550cfa18
equal deleted inserted replaced
58:1a38447a89fa 59:9226980e45a7
1 /*!
2 Helper traits to work with references or owned values of types and their subsets.
3 */
4
5 #[derive(Clone, Copy)]
6 pub enum EitherDecomp<A, B> {
7 Owned(A),
8 Borrowed(B),
9 }
10
11 /// A very basic implementation of [`Cow`] without a [`Clone`] trait dependency.
12 pub type MyCow<'b, X> = EitherDecomp<X, &'b X>;
13
14 impl<'b, X> std::ops::Deref for MyCow<'b, X> {
15 type Target = X;
16
17 #[inline]
18 fn deref(&self) -> &Self::Target {
19 match self {
20 EitherDecomp::Owned(x) => &x,
21 EitherDecomp::Borrowed(x) => x,
22 }
23 }
24 }
25
26 impl<'b, X> MyCow<'b, X> {
27 #[inline]
28 pub fn into_owned(self) -> X where X : Clone {
29 match self {
30 EitherDecomp::Owned(x) => x,
31 EitherDecomp::Borrowed(x) => x.clone(),
32 }
33 }
34 }
35
36 /// Trait for abitrary mathematical spaces.
37 pub trait Space : Instance<Self, Self::Decomp> {
38 /// Default decomposition for the space
39 type Decomp : Decomposition<Self>;
40 }
41
42 #[macro_export]
43 macro_rules! impl_basic_space {
44 ($($type:ty)*) => { $(
45 impl $crate::instance::Space for $type {
46 type Decomp = $crate::instance::BasicDecomposition;
47 }
48 )* };
49 ($type:ty where $($where:tt)*) => {
50 impl<$($where)*> $crate::instance::Space for $type {
51 type Decomp = $crate::instance::BasicDecomposition;
52 }
53 };
54 }
55
56 impl_basic_space!(u8 u16 u32 u64 u128 usize
57 i8 i16 i32 i64 i128 isize
58 f32 f64);
59
60 /// Marker type for decompositions to be used with [`Instance`].
61 pub trait Decomposition<X : Space> : Sized {
62 /// Possibly owned form of the decomposition
63 type Decomposition<'b> : Instance<X, Self> where X : 'b;
64 /// Unlikely owned form of the decomposition.
65 /// Type for a lightweight intermediate conversion that does not own the original variable.
66 /// Usually this is just a reference, but may also be a lightweight structure that
67 /// contains references; see the implementation for [`crate::direct_product::Pair`].
68 type Reference<'b> : Instance<X, Self> + Copy where X : 'b;
69
70 /// Left the lightweight reference type into a full decomposition type.
71 fn lift<'b>(r : Self::Reference<'b>) -> Self::Decomposition<'b>;
72 }
73
74 /// Most common [`Decomposition`] (into `Either<X, &'b X>`) that allows working with owned
75 /// values and all sorts of references.
76 #[derive(Copy, Clone, Debug)]
77 pub struct BasicDecomposition;
78
79 impl<X : Space + Clone> Decomposition<X> for BasicDecomposition {
80 type Decomposition<'b> = MyCow<'b, X> where X : 'b;
81 type Reference<'b> = &'b X where X : 'b;
82
83 #[inline]
84 fn lift<'b>(r : Self::Reference<'b>) -> Self::Decomposition<'b> {
85 MyCow::Borrowed(r)
86 }
87 }
88
89 /// Helper trait for functions to work with either owned values or references to either the
90 /// “principal type” `X` or types some present a subset of `X`. In the latter sense, this
91 /// generalises [`std::borrow::ToOwned`], [`std::borrow::Borrow`], and [`std::borrow::Cow`].
92 /// This type also includes iteratation facilities when `X` is a [`Collection`], to avoid
93 /// the possibly costly conversion of such subset types into `X`.
94 pub trait Instance<X : Space, D = <X as Space>::Decomp> : Sized where D : Decomposition<X> {
95 /// Decomposes self according to `decomposer`.
96 fn decompose<'b>(self) -> D::Decomposition<'b>
97 where Self : 'b, X : 'b;
98
99 /// Returns a lightweight instance of `self`.
100 fn ref_instance(&self) -> D::Reference<'_>;
101
102 /// Returns an owned instance of `X`, cloning or converting non-true instances when necessary.
103 fn own(self) -> X;
104
105 // ************** automatically implemented methods below from here **************
106
107 /// Returns an owned instance or reference to `X`, converting non-true instances when necessary.
108 ///
109 /// Default implementation uses [`Self::own`]. Consumes the input.
110 fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b {
111 MyCow::Owned(self.own())
112 }
113
114 #[inline]
115 /// Evaluates `f` on a reference to self.
116 ///
117 /// Default implementation uses [`Self::cow`]. Consumes the input.
118 fn eval<'b, R>(self, f : impl FnOnce(&X) -> R) -> R
119 where X : 'b, Self : 'b
120 {
121 f(&*self.cow())
122 }
123
124 #[inline]
125 /// Evaluates `f` or `g` depending on whether a reference or owned value is available.
126 ///
127 /// Default implementation uses [`Self::cow`]. Consumes the input.
128 fn either<'b, R>(
129 self,
130 f : impl FnOnce(X) -> R,
131 g : impl FnOnce(&X) -> R
132 ) -> R
133 where Self : 'b
134 {
135 match self.cow() {
136 EitherDecomp::Owned(x) => f(x),
137 EitherDecomp::Borrowed(x) => g(x),
138 }
139 }
140 }
141
142
143 impl<X : Space + Clone> Instance<X, BasicDecomposition> for X {
144 #[inline]
145 fn decompose<'b>(self) -> <BasicDecomposition as Decomposition<X>>::Decomposition<'b>
146 where Self : 'b, X : 'b
147 {
148 MyCow::Owned(self)
149 }
150
151 #[inline]
152 fn own(self) -> X {
153 self
154 }
155
156 #[inline]
157 fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b {
158 MyCow::Owned(self)
159 }
160
161 #[inline]
162 fn ref_instance(&self) -> <BasicDecomposition as Decomposition<X>>::Reference<'_> {
163 self
164 }
165 }
166
167 impl<'a, X : Space + Clone> Instance<X, BasicDecomposition> for &'a X {
168 #[inline]
169 fn decompose<'b>(self) -> <BasicDecomposition as Decomposition<X>>::Decomposition<'b>
170 where Self : 'b, X : 'b
171 {
172 MyCow::Borrowed(self)
173 }
174
175 #[inline]
176 fn own(self) -> X {
177 self.clone()
178 }
179
180 #[inline]
181 fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b {
182 MyCow::Borrowed(self)
183 }
184
185 #[inline]
186 fn ref_instance(&self) -> <BasicDecomposition as Decomposition<X>>::Reference<'_> {
187 *self
188 }
189 }
190
191 impl<'a, X : Space + Clone> Instance<X, BasicDecomposition> for &'a mut X {
192 #[inline]
193 fn decompose<'b>(self) -> <BasicDecomposition as Decomposition<X>>::Decomposition<'b>
194 where Self : 'b, X : 'b
195 {
196 EitherDecomp::Borrowed(self)
197 }
198
199 #[inline]
200 fn own(self) -> X {
201 self.clone()
202 }
203
204 #[inline]
205 fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b, X : Clone {
206 EitherDecomp::Borrowed(self)
207 }
208
209 #[inline]
210 fn ref_instance(&self) -> <BasicDecomposition as Decomposition<X>>::Reference<'_> {
211 *self
212 }
213 }
214
215 impl<'a, X : Space + Clone> Instance<X, BasicDecomposition> for MyCow<'a, X> {
216
217 #[inline]
218 fn decompose<'b>(self) -> <BasicDecomposition as Decomposition<X>>::Decomposition<'b>
219 where Self : 'b, X : 'b
220 {
221 self
222 }
223
224 #[inline]
225 fn own(self) -> X {
226 match self {
227 MyCow::Borrowed(a) => a.own(),
228 MyCow::Owned(b) => b.own()
229 }
230 }
231
232 #[inline]
233 fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b {
234 match self {
235 MyCow::Borrowed(a) => a.cow(),
236 MyCow::Owned(b) => b.cow()
237 }
238 }
239
240 #[inline]
241 fn ref_instance(&self) -> <BasicDecomposition as Decomposition<X>>::Reference<'_> {
242 match self {
243 MyCow::Borrowed(a) => a,
244 MyCow::Owned(b) => &b,
245 }
246 }
247 }
248
249 /// Marker type for mutable decompositions to be used with [`InstanceMut`].
250 pub trait DecompositionMut<X : Space> : Sized {
251 type ReferenceMut<'b> : InstanceMut<X, Self> where X : 'b;
252 }
253
254
255 /// Helper trait for functions to work with mutable references.
256 pub trait InstanceMut<X : Space , D = <X as Space>::Decomp> : Sized where D : DecompositionMut<X> {
257 /// Returns a mutable decomposition of self.
258 fn ref_instance_mut(&mut self) -> D::ReferenceMut<'_>;
259 }
260
261 impl<X : Space> DecompositionMut<X> for BasicDecomposition {
262 type ReferenceMut<'b> = &'b mut X where X : 'b;
263 }
264
265 /// This impl may seem pointless, but allows throwaway mutable scratch variables
266 impl<'a, X : Space> InstanceMut<X, BasicDecomposition> for X {
267 #[inline]
268 fn ref_instance_mut(&mut self)
269 -> <BasicDecomposition as DecompositionMut<X>>::ReferenceMut<'_>
270 {
271 self
272 }
273 }
274
275 impl<'a, X : Space> InstanceMut<X, BasicDecomposition> for &'a mut X {
276 #[inline]
277 fn ref_instance_mut(&mut self)
278 -> <BasicDecomposition as DecompositionMut<X>>::ReferenceMut<'_>
279 {
280 self
281 }
282 }

mercurial