1#![no_std]
2#![deny(missing_docs)]
3
4#[cfg(test)]
7#[macro_use]
8extern crate std;
9
10pub trait Encode {
12 type Target;
14 type Output;
16
17 fn encode(target: Self::Target) -> Self::Output;
19}
20
21pub trait ContextualEncode {
23 type Target;
25 type Context;
27 type Output;
29
30 fn encode(target: Self::Target, ctx: Self::Context) -> Self::Output;
32}
33
34pub trait Decode {
36 type Target;
38 type Output;
40
41 fn decode(target: Self::Target) -> Self::Output;
43}
44
45pub trait ContextualDecode {
47 type Target;
49 type Context;
51 type Output;
53
54 fn decode(value: Self::Target, ctx: Self::Context) -> Self::Output;
56}
57
58pub trait EncodeExt<'a, OUT>: Sized {
60 fn encode<E>(&'a self) -> OUT
62 where
63 E: Encode<Target = &'a Self, Output = OUT>;
64
65 fn encode_mut<E>(&'a mut self) -> OUT
67 where
68 E: Encode<Target = &'a mut Self, Output = OUT>;
69}
70
71impl<'a, T, OUT> EncodeExt<'a, OUT> for T {
72 fn encode<E>(&'a self) -> OUT
73 where
74 E: Encode<Target = &'a Self, Output = OUT>,
75 {
76 E::encode(self)
77 }
78
79 fn encode_mut<E>(&'a mut self) -> OUT
80 where
81 E: Encode<Target = &'a mut Self, Output = OUT>,
82 {
83 E::encode(self)
84 }
85}
86
87pub trait ContextualEncodeExt<'a, CTX, OUT>: Sized {
89 fn contextual_encode<E>(&'a self, ctx: CTX) -> OUT
91 where
92 E: ContextualEncode<Target = &'a Self, Context = CTX, Output = OUT>;
93
94 fn contextual_encode_mut<E>(&'a mut self, ctx: CTX) -> OUT
96 where
97 E: ContextualEncode<Target = &'a mut Self, Context = CTX, Output = OUT>;
98}
99
100impl<'a, T, CTX, OUT> ContextualEncodeExt<'a, CTX, OUT> for T {
101 fn contextual_encode<E>(&'a self, ctx: CTX) -> OUT
102 where
103 E: ContextualEncode<Target = &'a Self, Context = CTX, Output = OUT>,
104 {
105 E::encode(self, ctx)
106 }
107
108 fn contextual_encode_mut<E>(&'a mut self, ctx: CTX) -> OUT
109 where
110 E: ContextualEncode<Target = &'a mut Self, Context = CTX, Output = OUT>,
111 {
112 E::encode(self, ctx)
113 }
114}
115
116pub trait DecodeExt<'a, OUT>: Sized {
118 fn decode<D>(&'a self) -> OUT
120 where
121 D: Decode<Target = &'a Self, Output = OUT>;
122
123 fn decode_mut<D>(&'a mut self) -> OUT
125 where
126 D: Decode<Target = &'a mut Self, Output = OUT>;
127}
128
129impl<'a, T, OUT> DecodeExt<'a, OUT> for T {
130 fn decode<D>(&'a self) -> OUT
131 where
132 D: Decode<Target = &'a Self, Output = OUT>,
133 {
134 D::decode(self)
135 }
136
137 fn decode_mut<D>(&'a mut self) -> OUT
138 where
139 D: Decode<Target = &'a mut Self, Output = OUT>,
140 {
141 D::decode(self)
142 }
143}
144
145pub trait ContextualDecodeExt<'a, CTX, OUT>: Sized {
147 fn contextual_decode<D>(&'a self, ctx: CTX) -> OUT
149 where
150 D: ContextualDecode<Target = &'a Self, Context = CTX, Output = OUT>;
151
152 fn contextual_decode_mut<D>(&'a mut self, ctx: CTX) -> OUT
154 where
155 D: ContextualDecode<Target = &'a mut Self, Context = CTX, Output = OUT>;
156}
157
158impl<'a, T, CTX, OUT> ContextualDecodeExt<'a, CTX, OUT> for T {
159 fn contextual_decode<D>(&'a self, ctx: CTX) -> OUT
160 where
161 D: ContextualDecode<Target = &'a Self, Context = CTX, Output = OUT>,
162 {
163 D::decode(self, ctx)
164 }
165
166 fn contextual_decode_mut<D>(&'a mut self, ctx: CTX) -> OUT
167 where
168 D: ContextualDecode<Target = &'a mut Self, Context = CTX, Output = OUT>,
169 {
170 D::decode(self, ctx)
171 }
172}
173
174#[cfg(test)]
175mod property_based_test {
176 use super::*;
177 use quickcheck_macros::quickcheck;
178 use std::vec::Vec;
179
180 struct Raw<T>(T);
181
182 impl<T> Encode for Raw<T> {
183 type Target = T;
184 type Output = T;
185
186 fn encode(target: Self::Target) -> Self::Output {
187 target
188 }
189 }
190
191 impl<T> ContextualEncode for Raw<T> {
192 type Target = T;
193 type Context = ();
194 type Output = T;
195
196 fn encode(target: Self::Target, _: Self::Context) -> Self::Output {
197 target
198 }
199 }
200
201 impl<T> Decode for Raw<T> {
202 type Target = T;
203 type Output = T;
204
205 fn decode(target: Self::Target) -> Self::Output {
206 target
207 }
208 }
209
210 impl<T> ContextualDecode for Raw<T> {
211 type Target = T;
212 type Context = ();
213 type Output = T;
214
215 fn decode(target: Self::Target, _: Self::Context) -> Self::Output {
216 target
217 }
218 }
219
220 #[quickcheck]
221 fn equivalent_when_encode(value: Vec<u8>) {
222 let actual = value.encode::<Raw<_>>();
223 let expected = &value;
224 assert_eq!(actual, expected);
225 }
226
227 #[quickcheck]
228 fn equivalent_when_encode_mut(mut value: Vec<u8>) {
229 let expected = &mut value.clone();
230 let actual = value.encode_mut::<Raw<_>>();
231 assert_eq!(actual, expected);
232 }
233
234 #[quickcheck]
235 fn equivalent_when_contextual_encode(value: Vec<u8>) {
236 let actual = value.contextual_encode::<Raw<_>>(());
237 let expected = &value;
238 assert_eq!(actual, expected);
239 }
240
241 #[quickcheck]
242 fn equivalent_when_contextual_encode_mut(mut value: Vec<u8>) {
243 let expected = &mut value.clone();
244 let actual = value.contextual_encode_mut::<Raw<_>>(());
245 assert_eq!(actual, expected);
246 }
247
248 #[quickcheck]
249 fn equivalent_when_decode(value: Vec<u8>) {
250 let actual = value.decode::<Raw<_>>();
251 let expected = &value;
252 assert_eq!(actual, expected);
253 }
254
255 #[quickcheck]
256 fn equivalent_when_decode_mut(mut value: Vec<u8>) {
257 let expected = &mut value.clone();
258 let actual = value.decode_mut::<Raw<_>>();
259 assert_eq!(actual, expected);
260 }
261
262 #[quickcheck]
263 fn equivalent_when_contextual_decode(value: Vec<u8>) {
264 let actual = value.contextual_decode::<Raw<_>>(());
265 let expected = &value;
266 assert_eq!(actual, expected);
267 }
268
269 #[quickcheck]
270 fn equivalent_when_contextual_decode_mut(mut value: Vec<u8>) {
271 let expected = &mut value.clone();
272 let actual = value.contextual_decode_mut::<Raw<_>>(());
273 assert_eq!(actual, expected);
274 }
275}