core_ext/convert/
mod.rs

1//! # Core Convert Extensions
2//!
3//! Useful extensions to `core::convert` library.
4//!
5
6use core::convert::{Into, TryInto};
7use core::result::Result;
8
9/// Simple and safe type conversions to `self`. Relies on reciprocals `From` and `Into`, so as a consequence the implementation of at least one of them is required.
10///
11/// # Examples
12///
13/// ```
14/// use core_ext::convert::To;
15///
16/// struct A(u8);
17/// impl To for A {}
18///
19/// struct B(u8);
20/// impl From<A> for B {
21///     fn from(value: A) -> Self {
22///         Self(value.0 + 1)
23///     }
24/// }
25/// impl To for B {}
26///
27/// struct C(u8);
28/// impl From<B> for C {
29///     fn from(value: B) -> Self {
30///         Self(value.0 + 2)
31///     }
32/// }
33/// impl To for C {}
34///
35/// assert_eq!(5_u8, A(2).to::<B>().to::<C>().0)
36/// ```
37pub trait To {
38    fn to<T>(self) -> T
39    where
40        Self: Into<T>,
41    {
42        self.into()
43    }
44}
45
46/// Simple and safe type conversions to `self` that may fail in a controlled way under some circunstances.
47/// Relies on reciprocals `TryFrom` and `TryInto`, so as a consequence the implementation of at least one of them is required.
48///
49/// # Examples
50///
51/// ```
52/// use core_ext::convert::TryTo;
53///
54/// #[derive(Debug)]
55/// enum Error {}
56///
57/// struct A(u8);
58/// impl TryTo<Error> for A {}
59///
60/// struct B(u8);
61/// impl TryFrom<A> for B {
62///     type Error = Error;
63///     fn try_from(value: A) -> Result<Self,Error> {
64///         Ok(Self(value.0 + 1))
65///     }
66/// }
67/// impl TryTo<Error> for B {}
68///
69/// struct C(u8);
70/// impl TryFrom<B> for C {
71///     type Error = Error;
72///     fn try_from(value: B) -> Result<Self,Error> {
73///         Ok(Self(value.0 + 2))
74///     }
75/// }
76/// impl TryTo<Error> for C {}
77///
78/// assert_eq!(5_u8, A(2).try_to::<B>().unwrap().try_to::<C>().unwrap().0)
79/// ```
80pub trait TryTo<E> {
81    fn try_to<T>(self) -> Result<T, E>
82    where
83        Self: TryInto<T, Error = E>,
84    {
85        self.try_into()
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use core::convert::Infallible;
92
93    use super::*;
94
95    #[test]
96    fn test_to() {
97        #[derive(PartialEq, Debug)]
98        struct Type(u8);
99        impl From<u8> for Type {
100            fn from(value: u8) -> Self {
101                Type(value)
102            }
103        }
104        impl To for u8 {}
105        // insta::assert_yaml_snapshot!(2_u8.to::<A>());
106        assert_eq!(Type(2), 2_u8.to())
107    }
108
109    #[test]
110    fn test_to_chain() {
111        #[derive(PartialEq, Debug)]
112        struct A(u8);
113        #[derive(PartialEq, Debug)]
114        struct B(u8);
115        #[derive(PartialEq, Debug)]
116        struct C(u8);
117        impl From<u8> for A {
118            fn from(value: u8) -> Self {
119                A(value + 1)
120            }
121        }
122        impl From<A> for B {
123            fn from(value: A) -> Self {
124                B(value.0 + 1)
125            }
126        }
127        impl From<B> for C {
128            fn from(value: B) -> Self {
129                Self(value.0 + 1)
130            }
131        }
132        impl To for A {}
133        // impl To for u8 {}
134        impl To for B {}
135        assert_eq!(A(1), 0_u8.to());
136        assert_eq!(
137            C(4_u8),
138            1_u8.to::<A>() //
139                .to::<B>() //
140                .to::<C>()
141        );
142    }
143
144    #[test]
145    fn test_try_to() -> Result<(), Infallible> {
146        #[derive(PartialEq, Debug)]
147        struct Type(u8);
148        impl TryFrom<u8> for Type {
149            type Error = Infallible;
150
151            fn try_from(value: u8) -> Result<Self, Self::Error> {
152                Ok(Type(value))
153            }
154        }
155        impl TryTo<Infallible> for u8 {}
156        assert_eq!(Type(2), 2_u8.try_to()?);
157        Ok(())
158    }
159
160    #[test]
161    fn test_try_to_chain() -> Result<(), Infallible> {
162        #[derive(PartialEq, Debug)]
163        struct A(u8);
164        #[derive(PartialEq, Debug)]
165        struct B(u8);
166        #[derive(PartialEq, Debug)]
167        struct C(u8);
168        impl TryFrom<u8> for A {
169            type Error = Infallible;
170
171            fn try_from(value: u8) -> Result<Self, Self::Error> {
172                Ok(A(value + 1))
173            }
174        }
175        impl TryFrom<A> for B {
176            type Error = Infallible;
177
178            fn try_from(value: A) -> Result<Self, Self::Error> {
179                Ok(B(value.0 + 1))
180            }
181        }
182        impl TryFrom<B> for C {
183            type Error = Infallible;
184
185            fn try_from(value: B) -> Result<Self, Self::Error> {
186                Ok(Self(value.0 + 1))
187            }
188        }
189        impl TryTo<Infallible> for A {}
190        // impl To for u8 {}
191        impl TryTo<Infallible> for B {}
192        assert_eq!(A(1), 0_u8.try_to()?);
193        assert_eq!(
194            C(4_u8),
195            1_u8.try_to::<A>()? //
196                .try_to::<B>()? //
197                .try_to::<C>()?
198        );
199        Ok(())
200    }
201}