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}