1#[macro_export]
25macro_rules! impl_from {
26 (<$($generic:ident),+> in $from:ty => $this:ty $(,)?) => {
27 impl <$($generic),+> ::core::convert::From<$from> for $this {
28 fn from(from: $from) -> Self {
29 Self(from)
30 }
31 }
32 };
33
34 (<$($generic:ident),+> in $from:ty => $this:ty : $field:ident $(,)?) => {
35 impl <$($generic),+> ::core::convert::From<$from> for $this {
36 fn from(from: $from) -> Self {
37 Self { $field: from }
38 }
39 }
40 };
41
42 ($from:ty => $this:ty $(,)?) => {
43 impl ::core::convert::From<$from> for $this {
44 fn from(from: $from) -> Self {
45 Self(from)
46 }
47 }
48 };
49
50
51 ($from:ty => $this:ty : $field:ident $(,)?) => {
52 impl ::core::convert::From<$from> for $this {
53 fn from(from: $from) -> Self {
54 Self { $field : from }
55 }
56 }
57 };
58}
59
60#[macro_export]
73macro_rules! impl_from_for_primitive {
74 ($from:ty => $this:ty $(,)?) => {
75 impl ::core::convert::From<$from> for $this {
76 fn from(from: $from) -> $this {
77 <$this as ::core::convert::From<_>>::from(from.0)
78 }
79 }
80 };
81}
82
83#[macro_export]
100macro_rules! impl_newtype_from_into {
101 ($newtype:ty [<=>] $inner:ty $(,)?) => {
102 impl ::core::convert::From<$inner> for $newtype {
103 fn from(from: $inner) -> $newtype {
104 Self(from)
105 }
106 }
107
108 impl ::core::convert::From<$newtype> for $inner {
109 fn from(from: $newtype) -> $inner {
110 from.0
111 }
112 }
113 };
114}
115
116#[macro_export]
143macro_rules! impl_into {
144 (<$($generic:ident),+> in $this:ty => $inner:ty : $field:ident) => {
145 impl <$($generic),+> ::core::convert::Into<$inner> for $this {
146 fn into(self) -> $inner {
147 self.$field
148 }
149 }
150 };
151
152 (<$($generic:ident),+> in $this:ty => $inner:ty) => {
153 impl <$($generic),+> ::core::convert::Into<$inner> for $this {
154 fn into(self) -> $inner {
155 self.0
156 }
157 }
158 };
159
160 ($this:ty => $inner:ty) => {
161 impl ::core::convert::Into<$inner> for $this {
162 fn into(self) -> $inner {
163 self.0
164 }
165 }
166 };
167
168 ($this:ty => $inner:ty : $field:ident) => {
169 impl ::core::convert::Into<$inner> for $this {
170 fn into(self) -> $inner {
171 self.$field
172 }
173 }
174 };
175}
176
177#[cfg(test)]
178mod tests {
179 #![allow(clippy::from_over_into)]
180
181 use alloc::rc::Rc;
182
183 #[test]
184 fn newtype() {
185 struct Foo(usize);
186 impl_from!(usize => Foo);
187 impl_into!(Foo => usize);
188
189 static_assertions::assert_impl_all!(Foo: From<usize>, Into<usize>);
190
191 let foo = Foo::from(42);
192 assert_eq!(foo.0, 42);
193 }
194
195 #[test]
196 fn newtype_primitive() {
197 struct Foo(usize);
198 impl_from!(usize => Foo);
199 impl_from_for_primitive!(Foo => usize);
200
201 static_assertions::assert_impl_all!(Foo: From<usize>);
202 static_assertions::assert_impl_all!(usize: From<Foo>);
203
204 let foo = Foo::from(42);
205 assert_eq!(foo.0, 42);
206 }
207
208 #[test]
209 fn newtype_generic() {
210 struct Foo<T>(Rc<T>);
211 impl_from!(<T> in Rc<T> => Foo<T>);
212 impl_into!(<T> in Foo<T> => Rc<T>);
213
214 let foo = Foo::from(Rc::new(42_usize));
215 assert_eq!(*foo.0, 42);
216 }
217
218 #[test]
219 fn named_field() {
220 struct Foo {
221 inner: usize,
222 }
223 impl_from!(usize => Foo : inner);
224 impl_into!(Foo => usize : inner);
225
226 static_assertions::assert_impl_all!(Foo: From<usize>, Into<usize>);
227
228 let foo = Foo::from(42);
229 assert_eq!(foo.inner, 42);
230
231 struct MultiFoo {
232 small: u8,
233 big: u64,
234 }
235 impl_into!(MultiFoo => u8 : small);
236 impl_into!(MultiFoo => u64 : big);
237
238 static_assertions::assert_impl_all!(MultiFoo: Into<u8>, Into<u64>);
239
240 let foo = MultiFoo { small: 4, big: 42 };
241 assert_eq!(foo.small, 4);
242 assert_eq!(foo.big, 42);
243 }
244
245 #[test]
246 fn named_field_generic() {
247 struct Foo<T> {
248 inner: Rc<T>,
249 }
250 impl_from!(<T> in Rc<T> => Foo<T> : inner);
251 impl_into!(<T> in Foo<T> => Rc<T> : inner);
252
253 let foo = Foo::from(Rc::new(42_usize));
254 assert_eq!(*foo.inner, 42);
255 }
256}