1#[macro_export]
36macro_rules! impl_from {
37 (<$($generic:ident),+> in $($rest:tt)+) => {
38 $crate::impl_from!(@impl [$($generic),+] $($rest)+);
39 };
40
41 (<const $($rest:tt)+) => {
42 $crate::__impl_more_parse_generics!(@parse impl_from [] [] const $($rest)+);
43 };
44
45 (<$generic:ident, $($rest:tt)+) => {
46 $crate::__impl_more_parse_generics!(@parse impl_from [] [] $generic, $($rest)+);
47 };
48
49 (@impl [$($generic:tt)+] $from:ty => $this:ty $(,)?) => {
50 impl <$($generic)+> ::core::convert::From<$from> for $this {
51 fn from(from: $from) -> Self {
52 Self(from)
53 }
54 }
55 };
56
57 (@impl [$($generic:tt)+] $from:ty => $this:ty : $field:ident $(,)?) => {
58 impl <$($generic)+> ::core::convert::From<$from> for $this {
59 fn from(from: $from) -> Self {
60 Self { $field: from }
61 }
62 }
63 };
64
65 ($from:ty => $this:ty $(,)?) => {
66 impl ::core::convert::From<$from> for $this {
67 fn from(from: $from) -> Self {
68 Self(from)
69 }
70 }
71 };
72
73
74 ($from:ty => $this:ty : $field:ident $(,)?) => {
75 impl ::core::convert::From<$from> for $this {
76 fn from(from: $from) -> Self {
77 Self { $field : from }
78 }
79 }
80 };
81}
82
83#[macro_export]
96macro_rules! impl_from_for_primitive {
97 ($from:ty => $this:ty $(,)?) => {
98 impl ::core::convert::From<$from> for $this {
99 fn from(from: $from) -> $this {
100 <$this as ::core::convert::From<_>>::from(from.0)
101 }
102 }
103 };
104}
105
106#[macro_export]
123macro_rules! impl_newtype_from_into {
124 ($newtype:ty [<=>] $inner:ty $(,)?) => {
125 impl ::core::convert::From<$inner> for $newtype {
126 fn from(from: $inner) -> $newtype {
127 Self(from)
128 }
129 }
130
131 impl ::core::convert::From<$newtype> for $inner {
132 fn from(from: $newtype) -> $inner {
133 from.0
134 }
135 }
136 };
137}
138
139#[macro_export]
168macro_rules! impl_into {
169 (<$($generic:ident),+> in $($rest:tt)+) => {
170 $crate::impl_into!(@impl [$($generic),+] $($rest)+);
171 };
172
173 (<const $($rest:tt)+) => {
174 $crate::__impl_more_parse_generics!(@parse impl_into [] [] const $($rest)+);
175 };
176
177 (<$generic:ident, $($rest:tt)+) => {
178 $crate::__impl_more_parse_generics!(@parse impl_into [] [] $generic, $($rest)+);
179 };
180
181 (@impl [$($generic:tt)+] $this:ty => $inner:ty : $field:ident) => {
182 impl <$($generic)+> ::core::convert::Into<$inner> for $this {
183 fn into(self) -> $inner {
184 self.$field
185 }
186 }
187 };
188
189 (@impl [$($generic:tt)+] $this:ty => $inner:ty) => {
190 impl <$($generic)+> ::core::convert::Into<$inner> for $this {
191 fn into(self) -> $inner {
192 self.0
193 }
194 }
195 };
196
197 ($this:ty => $inner:ty) => {
198 impl ::core::convert::Into<$inner> for $this {
199 fn into(self) -> $inner {
200 self.0
201 }
202 }
203 };
204
205 ($this:ty => $inner:ty : $field:ident) => {
206 impl ::core::convert::Into<$inner> for $this {
207 fn into(self) -> $inner {
208 self.$field
209 }
210 }
211 };
212}
213
214#[cfg(test)]
215mod tests {
216 #![allow(clippy::from_over_into)]
217
218 use alloc::rc::Rc;
219
220 #[test]
221 fn newtype() {
222 struct Foo(usize);
223 impl_from!(usize => Foo);
224 impl_into!(Foo => usize);
225
226 static_assertions::assert_impl_all!(Foo: From<usize>, Into<usize>);
227
228 let foo = Foo::from(42);
229 assert_eq!(foo.0, 42);
230 }
231
232 #[test]
233 fn newtype_primitive() {
234 struct Foo(usize);
235 impl_from!(usize => Foo);
236 impl_from_for_primitive!(Foo => usize);
237
238 static_assertions::assert_impl_all!(Foo: From<usize>);
239 static_assertions::assert_impl_all!(usize: From<Foo>);
240
241 let foo = Foo::from(42);
242 assert_eq!(foo.0, 42);
243 }
244
245 #[test]
246 fn newtype_generic() {
247 struct Foo<T>(Rc<T>);
248 impl_from!(<T> in Rc<T> => Foo<T>);
249 impl_into!(<T> in Foo<T> => Rc<T>);
250
251 let foo = Foo::from(Rc::new(42_usize));
252 assert_eq!(*foo.0, 42);
253 }
254
255 #[test]
256 fn named_field() {
257 struct Foo {
258 inner: usize,
259 }
260 impl_from!(usize => Foo : inner);
261 impl_into!(Foo => usize : inner);
262
263 static_assertions::assert_impl_all!(Foo: From<usize>, Into<usize>);
264
265 let foo = Foo::from(42);
266 assert_eq!(foo.inner, 42);
267
268 struct MultiFoo {
269 small: u8,
270 big: u64,
271 }
272 impl_into!(MultiFoo => u8 : small);
273 impl_into!(MultiFoo => u64 : big);
274
275 static_assertions::assert_impl_all!(MultiFoo: Into<u8>, Into<u64>);
276
277 let foo = MultiFoo { small: 4, big: 42 };
278 assert_eq!(foo.small, 4);
279 assert_eq!(foo.big, 42);
280 }
281
282 #[test]
283 fn named_field_generic() {
284 struct Foo<T> {
285 inner: Rc<T>,
286 }
287 impl_from!(<T> in Rc<T> => Foo<T> : inner);
288 impl_into!(<T> in Foo<T> => Rc<T> : inner);
289
290 let foo = Foo::from(Rc::new(42_usize));
291 assert_eq!(*foo.inner, 42);
292 }
293}