try_specialize/type_fn.rs
1/// A trait that defines a mapping between an input type and an output type.
2///
3/// This trait is used to map specialization types to other wrapped or
4/// associated specialization types. If generic types `T1` and `T2` are proven
5/// to be equivalent, then types `<Mapper as TypeFn<T1>>::Output` and
6/// `<Mapper as TypeFn<T2>>::Output` are also equivalent.
7///
8/// This trait can also be used to specialize
9/// generics of the third-party library types that do not implement
10/// [`LifetimeFree`].
11///
12/// [`LifetimeFree`]: crate::LifetimeFree
13///
14/// # Examples
15///
16/// Custom data encoders and decoders with customizable per-type encoding
17/// and decoding errors and optimized byte array encoding and decoding.
18/// Full example code is available at
19/// [`examples/encode.rs`](https://github.com/zheland/try-specialize/blob/v0.1.2/examples/encode.rs).
20/// ```rust
21/// # use core::convert::Infallible;
22/// # use core::{array, slice};
23/// # use std::io::{self, Read, Write};
24/// #
25/// # use try_specialize::{Specialization, TypeFn};
26/// #
27/// # pub trait Encode {
28/// # type EncodeError;
29/// # fn encode_to<W>(&self, writer: &mut W) -> Result<(), Self::EncodeError>
30/// # where
31/// # W: ?Sized + Write;
32/// # }
33/// #
34/// # pub trait Decode: Sized {
35/// # type DecodeError;
36/// # fn decode_from<R>(reader: &mut R) -> Result<Self, Self::DecodeError>
37/// # where
38/// # R: ?Sized + Read;
39/// # }
40/// #
41/// # impl Encode for () {
42/// # type EncodeError = Infallible;
43/// #
44/// # #[inline]
45/// # fn encode_to<W>(&self, _writer: &mut W) -> Result<(), Self::EncodeError>
46/// # where
47/// # W: ?Sized + Write,
48/// # {
49/// # Ok(())
50/// # }
51/// # }
52/// #
53/// # impl Decode for () {
54/// # type DecodeError = Infallible;
55/// #
56/// # #[inline]
57/// # fn decode_from<R>(_reader: &mut R) -> Result<Self, Self::DecodeError>
58/// # where
59/// # R: ?Sized + Read,
60/// # {
61/// # Ok(())
62/// # }
63/// # }
64/// #
65/// # impl<T> Encode for Box<T>
66/// # where
67/// # T: Encode,
68/// # {
69/// # type EncodeError = T::EncodeError;
70/// #
71/// # #[inline]
72/// # fn encode_to<W>(&self, writer: &mut W) -> Result<(), Self::EncodeError>
73/// # where
74/// # W: ?Sized + Write,
75/// # {
76/// # T::encode_to(self, writer)
77/// # }
78/// # }
79/// #
80/// # impl<T> Decode for Box<T>
81/// # where
82/// # T: Decode,
83/// # {
84/// # type DecodeError = T::DecodeError;
85/// #
86/// # #[inline]
87/// # fn decode_from<R>(reader: &mut R) -> Result<Self, Self::DecodeError>
88/// # where
89/// # R: ?Sized + Read,
90/// # {
91/// # Ok(Self::new(T::decode_from(reader)?))
92/// # }
93/// # }
94/// #
95/// # impl Encode for u8 {
96/// # type EncodeError = io::Error;
97/// #
98/// # #[inline]
99/// # fn encode_to<W>(&self, writer: &mut W) -> Result<(), Self::EncodeError>
100/// # where
101/// # W: ?Sized + Write,
102/// # {
103/// # writer.write_all(&[*self])?;
104/// # Ok(())
105/// # }
106/// # }
107/// #
108/// # impl Decode for u8 {
109/// # type DecodeError = io::Error;
110/// #
111/// # #[inline]
112/// # fn decode_from<R>(reader: &mut R) -> Result<Self, Self::DecodeError>
113/// # where
114/// # R: ?Sized + Read,
115/// # {
116/// # let mut byte: Self = 0;
117/// # reader.read_exact(slice::from_mut(&mut byte))?;
118/// # Ok(byte)
119/// # }
120/// # }
121/// // ...
122///
123/// impl<T> Encode for [T]
124/// where
125/// T: Encode,
126/// {
127/// type EncodeError = T::EncodeError;
128///
129/// #[inline]
130/// fn encode_to<W>(&self, writer: &mut W) -> Result<(), Self::EncodeError>
131/// where
132/// W: ?Sized + Write,
133/// {
134/// if let Some(spec) = Specialization::<[T], [u8]>::try_new() {
135/// // Specialize self from `[T; N]` to `[u32; N]`
136/// let bytes: &[u8] = spec.specialize_ref(self);
137/// // Map type specialization to its associated error specialization.
138/// let spec_err = spec.rev().map::<MapToEncodeError>();
139/// writer
140/// .write_all(bytes)
141/// // Specialize error from `io::Error` to `Self::EncodeError`.
142/// .map_err(|err| spec_err.specialize(err))?;
143/// } else {
144/// for item in self {
145/// item.encode_to(writer)?;
146/// }
147/// }
148/// Ok(())
149/// }
150/// }
151///
152/// // ...
153/// # impl<T, const N: usize> Encode for [T; N]
154/// # where
155/// # T: Encode,
156/// # {
157/// # type EncodeError = T::EncodeError;
158/// #
159/// # #[inline]
160/// # fn encode_to<W>(&self, writer: &mut W) -> Result<(), Self::EncodeError>
161/// # where
162/// # W: ?Sized + Write,
163/// # {
164/// # self.as_slice().encode_to(writer)
165/// # }
166/// # }
167/// #
168/// # impl<T, const N: usize> Decode for [T; N]
169/// # where
170/// # T: Decode + Default,
171/// # {
172/// # type DecodeError = T::DecodeError;
173/// #
174/// # #[inline]
175/// # fn decode_from<R>(reader: &mut R) -> Result<Self, Self::DecodeError>
176/// # where
177/// # R: ?Sized + Read,
178/// # {
179/// # let spec = Specialization::<[T; N], [u8; N]>::try_new();
180/// #
181/// # if let Some(spec) = spec {
182/// # let mut array = [0; N];
183/// # reader
184/// # .read_exact(&mut array)
185/// # // Specialize `<[u8; N]>::Error` to `<[T; N]>::Error`
186/// # .map_err(|err| spec.rev().map::<MapToDecodeError>().specialize(err))?;
187/// # // Specialize `[u8; N]` to `[T; N]`
188/// # let array = spec.rev().specialize(array);
189/// # Ok(array)
190/// # } else {
191/// # // In real code it can be done without `Default` bound.
192/// # // But then the code would be unnecessarily complex for the example.
193/// # let mut array = array::from_fn(|_| T::default());
194/// # for item in &mut array {
195/// # *item = T::decode_from(reader)?;
196/// # }
197/// # Ok(array)
198/// # }
199/// # }
200/// # }
201/// #
202/// # struct MapToEncodeError;
203/// #
204/// # impl<T> TypeFn<T> for MapToEncodeError
205/// # where
206/// # T: ?Sized + Encode,
207/// # {
208/// # type Output = T::EncodeError;
209/// # }
210/// #
211/// # struct MapToDecodeError;
212/// # impl<T> TypeFn<T> for MapToDecodeError
213/// # where
214/// # T: Decode,
215/// # {
216/// # type Output = T::DecodeError;
217/// # }
218/// #
219/// # let mut array_buf = [0; 8];
220/// # let mut buf = &mut array_buf[..];
221/// # [1_u8, 2, 3].encode_to(&mut buf).unwrap();
222/// # 4_u8.encode_to(&mut buf).unwrap();
223/// # [(), (), (), ()].encode_to(&mut buf).unwrap();
224/// # [5_u8, 6, 7, 8].map(Box::new).encode_to(&mut buf).unwrap();
225/// # assert!(9_u8.encode_to(&mut buf).is_err());
226/// # assert!([9_u8, 10].encode_to(&mut buf).is_err());
227/// # ().encode_to(&mut buf).unwrap();
228/// # [(), (), ()].encode_to(&mut buf).unwrap();
229/// # assert!([9_u8, 10].map(Box::new).encode_to(&mut buf).is_err());
230/// # assert_eq!(array_buf, [1, 2, 3, 4, 5, 6, 7, 8]);
231/// #
232/// # let buf = &mut array_buf.as_slice();
233/// # assert_eq!(u8::decode_from(buf).unwrap(), 1);
234/// # assert_eq!(<[u8; 4]>::decode_from(buf).unwrap(), [2, 3, 4, 5]);
235/// # assert_eq!(<[(); 16]>::decode_from(buf).unwrap(), [(); 16]);
236/// # assert_eq!(<[u8; 1]>::decode_from(buf).unwrap(), [6]);
237/// # assert_eq!(
238/// # <[Box<u8>; 2]>::decode_from(buf).unwrap(),
239/// # [Box::new(7), Box::new(8)]
240/// # );
241/// # assert!(u8::decode_from(buf).is_err());
242/// # assert!(<[u8; 1]>::decode_from(buf).is_err());
243/// # assert_eq!(<[(); 2]>::decode_from(buf).unwrap(), [(); 2]);
244/// # assert!(<[Box<u8>; 2]>::decode_from(buf).is_err());
245/// ```
246///
247/// We can't use `reader.read_exact(&mut array)?;` in the example above because
248/// its error variant is `io::Error` while the function error variant is
249/// `T::Error`. But we can use the same specialization, but reversed and mapped:
250/// - `[T; N] => [u8; N]`,
251/// - with `.rev()`: `[u8; N] => [T; N]`,
252/// - with `.map::<MapError>()`: `<[u8; N] as Decode>::Error => <[T; N] as
253/// Decode>::Error`,
254/// - and for the compiler `<[u8; N] as Decode>::Error` and `io::Error` are
255/// equal types, so we can specialize the error as well: `io::Error => <[T; N]
256/// as Decode>::Error`.
257///
258/// Truncated synthetic example with multiple generics specialization for a
259/// third-party type:
260/// ```rust
261/// # #[cfg(feature = "std")] {
262/// use try_specialize::{Specialization, TypeFn};
263///
264/// fn some_generic_fn<K, V>(value: hashbrown::HashMap<K, V>) -> &'static str {
265/// struct MapIntoHashMap;
266/// impl<K, V> TypeFn<(K, V)> for MapIntoHashMap {
267/// type Output = hashbrown::HashMap<K, V>;
268/// }
269///
270/// if let Some(spec) = Specialization::<(K, V), (u32, char)>::try_new() {
271/// let spec = spec.map::<MapIntoHashMap>();
272/// let value = spec.specialize(value);
273/// specialized_impl(value)
274/// } else {
275/// default_impl(value)
276/// }
277/// }
278///
279/// fn default_impl<K, V>(value: hashbrown::HashMap<K, V>) -> &'static str {
280/// // ...
281/// # "default impl"
282/// }
283///
284/// fn specialized_impl(value: hashbrown::HashMap<u32, char>) -> &'static str {
285/// // ...
286/// # "specialized impl"
287/// }
288/// #
289/// # assert_eq!(
290/// # some_generic_fn([(0_i32, 'a'), (1, 'b'), (2, 'c')].into_iter().collect()),
291/// # "default impl"
292/// # );
293/// #
294/// # assert_eq!(
295/// # some_generic_fn(
296/// # [(0_u32, "zero"), (1, "one"), (2, "two")]
297/// # .into_iter()
298/// # .collect()
299/// # ),
300/// # "default impl"
301/// # );
302/// #
303/// # assert_eq!(
304/// # some_generic_fn([(0_u32, 'a'), (1, 'b'), (2, 'c')].into_iter().collect()),
305/// # "specialized impl"
306/// # );
307/// # }
308/// ```
309pub trait TypeFn<T>
310where
311 T: ?Sized,
312{
313 /// The returned type.
314 type Output: ?Sized;
315}