|
1 | 1 | # What `#[derive(Into)]` generates
|
2 | 2 |
|
3 |
| -This derive creates the the exact opposite of [`#[derive(From)]`](crate::From). |
| 3 | +This derive creates the exact opposite of `#[derive(From)]`. |
4 | 4 | Instead of allowing you to create a new instance of the struct from the values
|
5 |
| -it should contain, it allows you to extract the values from the struct. |
6 |
| -One thing to note is that this derive doesn't actually generate an |
7 |
| -implementation for the `Into` trait. |
8 |
| -Instead it derives `From` for the values contained in the struct and thus has an |
9 |
| -indirect implementation of `Into` as recommended by the |
10 |
| -[docs](https://doc.rust-lang.org/core/convert/trait.Into.html). |
| 5 | +it should contain, it allows you to extract the values from the struct. One |
| 6 | +thing to note is that this derive doesn't actually generate an implementation |
| 7 | +for the `Into` trait. Instead, it derives `From` for the values contained in |
| 8 | +the struct and thus has an indirect implementation of `Into` as |
| 9 | +[recommended by the docs][1]. |
11 | 10 |
|
12 | 11 |
|
13 | 12 |
|
14 | 13 |
|
15 |
| -## Example usage |
| 14 | +## Structs |
| 15 | + |
| 16 | +For structs with a single field you can call `.into()` to extract the inner type. |
16 | 17 |
|
17 | 18 | ```rust
|
18 | 19 | # use derive_more::Into;
|
19 | 20 | #
|
20 |
| -// Allow converting into i32 |
21 |
| -#[derive(Into, PartialEq)] |
22 |
| -struct MyInt(i32); |
23 |
| - |
24 |
| -// Additionally convert refs to the inner type refs |
25 |
| -#[derive(Into, PartialEq)] |
26 |
| -#[into(owned, ref, ref_mut)] |
27 |
| -struct MyInt64(i64); |
28 |
| - |
29 |
| -// Specify additional conversions |
30 |
| -#[derive(Into, PartialEq)] |
31 |
| -#[into(types(i16, i32))] |
32 |
| -struct MyInt8(i8); |
33 |
| - |
34 |
| -// Even for ref types |
35 |
| -#[derive(Into, PartialEq)] |
36 |
| -#[into(owned, ref(types(i64)))] |
37 |
| -struct MyInt64Wrapped(MyInt64); |
38 |
| - |
39 |
| -assert!(i32::from(MyInt(2)) == 2i32); |
40 |
| -assert!(i64::from(MyInt64(6)) == 6i64); |
41 |
| -assert!(<&i64>::from(&MyInt64(6)) == &6i64); |
42 |
| -assert!(<&mut i64>::from(&mut MyInt64(6)) == &mut 6i64); |
43 |
| -assert!(i8::from(MyInt8(7)) == 7i8); |
44 |
| -assert!(i16::from(MyInt8(7)) == 7i16); |
45 |
| -assert!(i32::from(MyInt8(7)) == 7i32); |
46 |
| -assert!(MyInt64::from(MyInt64Wrapped(MyInt64(1))) == MyInt64(1)); |
47 |
| -assert!(<&MyInt64>::from(&MyInt64Wrapped(MyInt64(1))) == &MyInt64(1)); |
48 |
| -assert!(<&i64>::from(&MyInt64Wrapped(MyInt64(1))) == &1i64); |
49 |
| -``` |
50 |
| - |
51 |
| - |
52 |
| - |
| 21 | +#[derive(Debug, Into, PartialEq)] |
| 22 | +struct Int(i32); |
53 | 23 |
|
54 |
| -## Tuple structs |
| 24 | +assert_eq!(2, Int(2).into()); |
| 25 | +``` |
55 | 26 |
|
56 |
| -When deriving `Into` for a tuple struct with a single field (i.e. a newtype) like this: |
| 27 | +For structs having multiple fields, `.into()` extracts a tuple containing the |
| 28 | +desired content for each field. |
57 | 29 |
|
58 | 30 | ```rust
|
59 | 31 | # use derive_more::Into;
|
60 | 32 | #
|
61 |
| -#[derive(Into)] |
62 |
| -struct MyInt(i32); |
63 |
| -``` |
64 |
| - |
65 |
| -Code like this will be generated: |
| 33 | +#[derive(Debug, Into, PartialEq)] |
| 34 | +struct Point(i32, i32); |
66 | 35 |
|
67 |
| -```rust |
68 |
| -# struct MyInt(i32); |
69 |
| -impl ::core::convert::From<MyInt> for (i32) { |
70 |
| - fn from(original: MyInt) -> (i32) { |
71 |
| - (original.0) |
72 |
| - } |
73 |
| -} |
| 36 | +assert_eq!((1, 2), Point(1, 2).into()); |
74 | 37 | ```
|
75 | 38 |
|
76 |
| -The behaviour is a bit different when deriving for a struct with multiple |
77 |
| -fields, since it returns a tuple. For instance when deriving for a tuple struct |
78 |
| -with two fields like this: |
| 39 | +To specify concrete types for deriving conversions into, use `#[into(<types>)]`. |
79 | 40 |
|
80 | 41 | ```rust
|
| 42 | +# use std::borrow::Cow; |
| 43 | +# |
81 | 44 | # use derive_more::Into;
|
82 | 45 | #
|
83 |
| -#[derive(Into)] |
84 |
| -struct MyInts(i32, i32); |
85 |
| -``` |
| 46 | +#[derive(Debug, Into, PartialEq)] |
| 47 | +#[into(Cow<'static, str>, String)] |
| 48 | +struct Str(Cow<'static, str>); |
86 | 49 |
|
87 |
| -Code like this will be generated: |
| 50 | +assert_eq!("String".to_owned(), String::from(Str("String".into()))); |
| 51 | +assert_eq!(Cow::Borrowed("Cow"), <Cow<_>>::from(Str("Cow".into()))); |
88 | 52 |
|
89 |
| -```rust |
90 |
| -# struct MyInts(i32, i32); |
91 |
| -impl ::core::convert::From<MyInts> for (i32, i32) { |
92 |
| - fn from(original: MyInts) -> (i32, i32) { |
93 |
| - (original.0, original.1) |
94 |
| - } |
| 53 | +#[derive(Debug, Into, PartialEq)] |
| 54 | +#[into((i64, i64), (i32, i32))] |
| 55 | +struct Point { |
| 56 | + x: i32, |
| 57 | + y: i32, |
95 | 58 | }
|
96 |
| -``` |
97 |
| - |
98 |
| - |
99 | 59 |
|
| 60 | +assert_eq!((1_i64, 2_i64), Point { x: 1_i32, y: 2_i32 }.into()); |
| 61 | +assert_eq!((3_i32, 4_i32), Point { x: 3_i32, y: 4_i32 }.into()); |
| 62 | +``` |
100 | 63 |
|
101 |
| -## Regular structs |
102 |
| - |
103 |
| -For regular structs almost the same code is generated as for tuple structs |
104 |
| -except in the way the field values are assigned to the new struct. |
105 |
| -When deriving for a regular struct with a single field like this: |
| 64 | +In addition to converting to owned types, this macro supports deriving into |
| 65 | +reference (mutable or not) via `#[into(ref(...))]`/`#[into(ref_mut(...))]`. |
106 | 66 |
|
107 | 67 | ```rust
|
108 | 68 | # use derive_more::Into;
|
109 | 69 | #
|
110 |
| -#[derive(Into)] |
111 |
| -struct Point1D { |
112 |
| - x: i32, |
113 |
| -} |
114 |
| -``` |
| 70 | +#[derive(Debug, Into, PartialEq)] |
| 71 | +#[into(owned, ref(i32), ref_mut)] |
| 72 | +struct Int(i32); |
115 | 73 |
|
116 |
| -Code like this will be generated: |
117 |
| - |
118 |
| -```rust |
119 |
| -# struct Point1D { |
120 |
| -# x: i32, |
121 |
| -# } |
122 |
| -impl ::core::convert::From<Point1D> for (i32) { |
123 |
| - fn from(original: Point1D) -> (i32) { |
124 |
| - (original.x) |
125 |
| - } |
126 |
| -} |
| 74 | +assert_eq!(2, Int(2).into()); |
| 75 | +assert_eq!(&2, <&i32>::from(&Int(2))); |
| 76 | +assert_eq!(&mut 2, <&mut i32>::from(&mut Int(2))); |
127 | 77 | ```
|
128 | 78 |
|
129 |
| -The behaviour is again a bit different when deriving for a struct with multiple |
130 |
| -fields, because this also returns a tuple. For instance when deriving for a |
131 |
| -tuple struct with two fields like this: |
| 79 | +In case there are fields, that shouldn't be included in the conversion, use the |
| 80 | +`#[into(skip)]` attribute. |
132 | 81 |
|
133 | 82 | ```rust
|
| 83 | +# use std::marker::PhantomData; |
| 84 | +# |
134 | 85 | # use derive_more::Into;
|
135 | 86 | #
|
136 |
| -#[derive(Into)] |
137 |
| -struct Point2D { |
138 |
| - x: i32, |
139 |
| - y: i32, |
| 87 | +# struct Gram; |
| 88 | +# |
| 89 | +#[derive(Debug, Into, PartialEq)] |
| 90 | +#[into(i32, i64, i128)] |
| 91 | +struct Mass<Unit> { |
| 92 | + value: i32, |
| 93 | + #[into(skip)] |
| 94 | + _unit: PhantomData<Unit>, |
140 | 95 | }
|
141 | 96 |
|
142 |
| -``` |
143 |
| - |
144 |
| -Code like this will be generated: |
145 |
| - |
146 |
| -```rust |
147 |
| -# struct Point2D { |
148 |
| -# x: i32, |
149 |
| -# y: i32, |
| 97 | +assert_eq!(5, Mass::<Gram>::new(5).into()); |
| 98 | +assert_eq!(5_i64, Mass::<Gram>::new(5).into()); |
| 99 | +assert_eq!(5_i128, Mass::<Gram>::new(5).into()); |
| 100 | +# |
| 101 | +# impl<Unit> Mass<Unit> { |
| 102 | +# fn new(value: i32) -> Self { |
| 103 | +# Self { |
| 104 | +# value, |
| 105 | +# _unit: PhantomData, |
| 106 | +# } |
| 107 | +# } |
150 | 108 | # }
|
151 |
| -impl ::core::convert::From<Point2D> for (i32, i32) { |
152 |
| - fn from(original: Point2D) -> (i32, i32) { |
153 |
| - (original.x, original.y) |
154 |
| - } |
155 |
| -} |
156 | 109 | ```
|
157 | 110 |
|
| 111 | +## Enums |
| 112 | + |
| 113 | +Deriving `Into` for enums is not supported as it would not always be successful, |
| 114 | +so `TryInto` should be used instead. |
158 | 115 |
|
159 | 116 |
|
160 | 117 |
|
161 |
| -## Enums |
162 | 118 |
|
163 |
| -Deriving `Into` for enums is not supported as it would not always be successful. |
164 |
| -This is what the currently unstable |
165 |
| -[`TryInto`](https://doc.rust-lang.org/core/convert/trait.TryInto.html) should be |
166 |
| -used for, which is currently not supported by this library. |
| 119 | +[1]: https://doc.rust-lang.org/core/convert/trait.Into.html |
0 commit comments