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}