impl_more/
from.rs

1/// Implement [`From`] for a struct.
2///
3/// # Examples
4/// With a newtype struct:
5/// ```
6/// use impl_more::impl_from;
7///
8/// struct Foo(String);
9/// impl_from!(String => Foo);
10///
11/// let foo = Foo::from("bar".to_owned());
12/// ```
13///
14/// With a named field struct with type parameters:
15/// ```
16/// use std::rc::Rc;
17/// use impl_more::impl_from;
18///
19/// struct Foo<T> { inner: Rc<T> }
20/// impl_from!(<T> in Rc<T> => Foo<T> : inner);
21///
22/// let foo = Foo::from(Rc::new("bar".to_owned()));
23/// ```
24#[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/// Implement [`From`] for a primitive.
61///
62/// # Examples
63/// With a newtype struct:
64/// ```
65/// use impl_more::impl_from_for_primitive;
66///
67/// struct Checked(bool);
68/// impl_from_for_primitive!(bool; from Checked);
69///
70/// let foo = bool::from(Checked(true));
71/// ```
72#[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/// Implement [`Into`] for a struct.
84///
85/// # Examples
86/// With a newtype struct:
87/// ```
88/// use impl_more::impl_into;
89///
90/// struct Foo(String);
91///
92/// impl_into!(Foo => String);
93///
94/// let foo = Foo("bar".to_owned());
95/// let foo_str: String = foo.into();
96/// ```
97///
98/// With a named field struct with type parameters:
99/// ```
100/// use std::rc::Rc;
101/// use impl_more::impl_into;
102///
103/// struct Foo<T> { inner: Rc<T> }
104/// impl_into!(<T> in Foo<T> => Rc<T> : inner);
105///
106/// let foo = Foo { inner: Rc::new("bar".to_owned()) };
107/// let _: Rc<String> = foo.into();
108/// ```
109#[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}