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 ($this:ty; from $from: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]
110macro_rules! impl_into {
111 (<$($generic:ident),+> in $this:ty => $inner:ty : $field:ident) => {
112 impl <$($generic),+> ::core::convert::Into<$inner> for $this {
113 fn into(self) -> $inner {
114 self.$field
115 }
116 }
117 };
118
119 (<$($generic:ident),+> in $this:ty => $inner:ty) => {
120 impl <$($generic),+> ::core::convert::Into<$inner> for $this {
121 fn into(self) -> $inner {
122 self.0
123 }
124 }
125 };
126
127 ($this:ty => $inner:ty) => {
128 impl ::core::convert::Into<$inner> for $this {
129 fn into(self) -> $inner {
130 self.0
131 }
132 }
133 };
134
135 ($this:ty => $inner:ty : $field:ident) => {
136 impl ::core::convert::Into<$inner> for $this {
137 fn into(self) -> $inner {
138 self.$field
139 }
140 }
141 };
142}
143
144#[cfg(test)]
145mod tests {
146 #![allow(clippy::from_over_into)]
147
148 use alloc::rc::Rc;
149
150 #[test]
151 fn newtype() {
152 struct Foo(usize);
153 impl_from!(usize => Foo);
154 impl_into!(Foo => usize);
155
156 static_assertions::assert_impl_all!(Foo: From<usize>, Into<usize>);
157
158 let foo = Foo::from(42);
159 assert_eq!(foo.0, 42);
160 }
161
162 #[test]
163 fn newtype_primitive() {
164 struct Foo(usize);
165 impl_from!(usize => Foo);
166 impl_from_for_primitive!(usize; from Foo);
167
168 static_assertions::assert_impl_all!(Foo: From<usize>);
169 static_assertions::assert_impl_all!(usize: From<Foo>);
170
171 let foo = Foo::from(42);
172 assert_eq!(foo.0, 42);
173 }
174
175 #[test]
176 fn newtype_generic() {
177 struct Foo<T>(Rc<T>);
178 impl_from!(<T> in Rc<T> => Foo<T>);
179 impl_into!(<T> in Foo<T> => Rc<T>);
180
181 let foo = Foo::from(Rc::new(42_usize));
182 assert_eq!(*foo.0, 42);
183 }
184
185 #[test]
186 fn named_field() {
187 struct Foo {
188 inner: usize,
189 }
190 impl_from!(usize => Foo : inner);
191 impl_into!(Foo => usize : inner);
192
193 static_assertions::assert_impl_all!(Foo: From<usize>, Into<usize>);
194
195 let foo = Foo::from(42);
196 assert_eq!(foo.inner, 42);
197
198 struct MultiFoo {
199 small: u8,
200 big: u64,
201 }
202 impl_into!(MultiFoo => u8 : small);
203 impl_into!(MultiFoo => u64 : big);
204
205 static_assertions::assert_impl_all!(MultiFoo: Into<u8>, Into<u64>);
206
207 let foo = MultiFoo { small: 4, big: 42 };
208 assert_eq!(foo.small, 4);
209 assert_eq!(foo.big, 42);
210 }
211
212 #[test]
213 fn named_field_generic() {
214 struct Foo<T> {
215 inner: Rc<T>,
216 }
217 impl_from!(<T> in Rc<T> => Foo<T> : inner);
218 impl_into!(<T> in Foo<T> => Rc<T> : inner);
219
220 let foo = Foo::from(Rc::new(42_usize));
221 assert_eq!(*foo.inner, 42);
222 }
223}