|
1 | 1 | # What `#[derive(FromStr)]` generates
|
2 | 2 |
|
3 |
| -Deriving `FromStr` only works for enums with no fields |
4 |
| -or newtypes, i.e structs with only a single |
5 |
| -field. The result is that you will be able to call the `parse()` method on a |
6 |
| -string to convert it to your newtype. This only works when the type that is |
7 |
| -contained in the type implements `FromStr`. |
| 3 | +Deriving `FromStr` only works for enums/structs with no fields |
| 4 | +or newtypes (structs with only a single field). The result is |
| 5 | +that you will be able to call the `parse()` method on a string |
| 6 | +to convert it to your newtype. This only works when the wrapped |
| 7 | +type implements `FromStr` itself. |
8 | 8 |
|
9 | 9 |
|
10 | 10 |
|
11 | 11 |
|
12 |
| -## Example usage |
13 |
| - |
14 |
| -```rust |
15 |
| -# use derive_more::FromStr; |
16 |
| -# |
17 |
| -#[derive(FromStr, Debug, Eq, PartialEq)] |
18 |
| -struct MyInt(i32); |
19 |
| - |
20 |
| -#[derive(FromStr, Debug, Eq, PartialEq)] |
21 |
| -struct Point1D{ |
22 |
| - x: i32, |
23 |
| -} |
24 |
| - |
25 |
| -assert_eq!(MyInt(5), "5".parse().unwrap()); |
26 |
| -assert_eq!(Point1D{x: 100}, "100".parse().unwrap()); |
27 |
| -``` |
28 |
| - |
| 12 | +## Forwarding |
29 | 13 |
|
| 14 | +Deriving forwarding implementation is only supported for newtypes |
| 15 | +(structs with only a single field). |
30 | 16 |
|
31 | 17 |
|
32 |
| -## Tuple structs |
| 18 | +### Tuple structs |
33 | 19 |
|
34 | 20 | When deriving `FromStr` for a tuple struct with one field:
|
35 |
| - |
36 | 21 | ```rust
|
37 | 22 | # use derive_more::FromStr;
|
38 | 23 | #
|
39 |
| -#[derive(FromStr)] |
| 24 | +#[derive(FromStr, Debug, Eq, PartialEq)] |
40 | 25 | struct MyInt(i32);
|
41 |
| -``` |
42 | 26 |
|
43 |
| -Code like this will be generated: |
| 27 | +assert_eq!("5".parse::<MyInt>().unwrap(), MyInt(5)); |
| 28 | +``` |
44 | 29 |
|
| 30 | +Code like this is generated: |
45 | 31 | ```rust
|
46 | 32 | # struct MyInt(i32);
|
47 | 33 | impl derive_more::core::str::FromStr for MyInt {
|
48 | 34 | type Err = <i32 as derive_more::core::str::FromStr>::Err;
|
49 |
| - fn from_str(src: &str) -> Result<Self, <i32 as derive_more::core::str::FromStr>::Err> { |
50 |
| - return Ok(MyInt(i32::from_str(src)?)); |
| 35 | + fn from_str(s: &str) -> Result<Self, Self::Err> { |
| 36 | + Ok(Self(i32::from_str(s)?)) |
51 | 37 | }
|
52 | 38 | }
|
53 | 39 | ```
|
54 | 40 |
|
55 | 41 |
|
56 |
| - |
57 |
| - |
58 |
| -## Regular structs |
| 42 | +### Regular structs |
59 | 43 |
|
60 | 44 | When deriving `FromStr` for a regular struct with one field:
|
61 |
| - |
62 | 45 | ```rust
|
63 | 46 | # use derive_more::FromStr;
|
64 | 47 | #
|
65 |
| -#[derive(FromStr)] |
| 48 | +#[derive(FromStr, Debug, Eq, PartialEq)] |
66 | 49 | struct Point1D {
|
67 | 50 | x: i32,
|
68 | 51 | }
|
69 |
| -``` |
70 | 52 |
|
71 |
| -Code like this will be generated: |
| 53 | +assert_eq!("100".parse::<Point1D>().unwrap(), Point1D { x: 100 }); |
| 54 | +``` |
72 | 55 |
|
| 56 | +Code like this is generated: |
73 | 57 | ```rust
|
74 | 58 | # struct Point1D {
|
75 | 59 | # x: i32,
|
76 | 60 | # }
|
77 | 61 | impl derive_more::core::str::FromStr for Point1D {
|
78 | 62 | type Err = <i32 as derive_more::core::str::FromStr>::Err;
|
79 |
| - fn from_str(src: &str) -> Result<Self, <i32 as derive_more::core::str::FromStr>::Err> { |
80 |
| - return Ok(Point1D { |
81 |
| - x: i32::from_str(src)?, |
82 |
| - }); |
| 63 | + fn from_str(s: &str) -> Result<Self, Self::Err> { |
| 64 | + Ok(Self { |
| 65 | + x: i32::from_str(s)?, |
| 66 | + }) |
83 | 67 | }
|
84 | 68 | }
|
85 | 69 | ```
|
86 | 70 |
|
87 | 71 |
|
88 | 72 |
|
89 | 73 |
|
90 |
| -## Enums |
| 74 | +## Flat representation |
91 | 75 |
|
92 |
| -When deriving `FromStr` for an enums with variants with no fields it will |
93 |
| -generate a `from_str` method that converts strings that match the variant name |
94 |
| -to the variant. If using a case insensitive match would give a unique variant |
95 |
| -(i.e you dont have both a `MyEnum::Foo` and a `MyEnum::foo` variant) then case |
96 |
| -insensitive matching will be used, otherwise it will fall back to exact string |
97 |
| -matching. |
| 76 | +Deriving flat string representation is only supported for empty enums and |
| 77 | +structs (with no fields). |
98 | 78 |
|
99 |
| -Since the string may not match any variants an error type is needed, so the |
100 |
| -`derive_more::FromStrError` will be used for that purpose. |
101 | 79 |
|
102 |
| -e.g. Given the following enum: |
| 80 | +### Empty enums |
| 81 | + |
| 82 | +When deriving `FromStr` for enums with empty variants, it will generate a |
| 83 | +`from_str()` method converting strings matching the variant name to the variant. |
| 84 | +If using a case-insensitive match would give a unique variant (i.e. you don't have |
| 85 | +both `MyEnum::Foo` and `MyEnum::foo` variants), then case-insensitive matching will |
| 86 | +be used, otherwise it will fall back to exact string matching. |
103 | 87 |
|
| 88 | +Since the string may not match any variants an error type is needed, so the |
| 89 | +`derive_more::FromStrError` is used for that purpose. |
| 90 | + |
| 91 | +Given the following enum: |
104 | 92 | ```rust
|
105 | 93 | # use derive_more::FromStr;
|
106 | 94 | #
|
107 |
| -#[derive(FromStr)] |
| 95 | +#[derive(FromStr, Debug, Eq, PartialEq)] |
108 | 96 | enum EnumNoFields {
|
109 | 97 | Foo,
|
110 | 98 | Bar,
|
111 | 99 | Baz,
|
| 100 | + BaZ, |
112 | 101 | }
|
113 |
| -``` |
114 | 102 |
|
115 |
| -Code like this will be generated: |
| 103 | +assert_eq!("foo".parse::<EnumNoFields>().unwrap(), EnumNoFields::Foo); |
| 104 | +assert_eq!("Foo".parse::<EnumNoFields>().unwrap(), EnumNoFields::Foo); |
| 105 | +assert_eq!("FOO".parse::<EnumNoFields>().unwrap(), EnumNoFields::Foo); |
| 106 | + |
| 107 | +assert_eq!("Bar".parse::<EnumNoFields>().unwrap(), EnumNoFields::Bar); |
| 108 | +assert_eq!("bar".parse::<EnumNoFields>().unwrap(), EnumNoFields::Bar); |
| 109 | + |
| 110 | +assert_eq!("Baz".parse::<EnumNoFields>().unwrap(), EnumNoFields::Baz); |
| 111 | +assert_eq!("BaZ".parse::<EnumNoFields>().unwrap(), EnumNoFields::BaZ); |
| 112 | +assert_eq!( |
| 113 | + "other".parse::<EnumNoFields>().unwrap_err().to_string(), |
| 114 | + "Invalid `EnumNoFields` string representation", |
| 115 | +); |
| 116 | +``` |
116 | 117 |
|
| 118 | +Code like this is generated: |
117 | 119 | ```rust
|
118 | 120 | # enum EnumNoFields {
|
119 | 121 | # Foo,
|
120 | 122 | # Bar,
|
121 | 123 | # Baz,
|
| 124 | +# BaZ, |
122 | 125 | # }
|
123 | 126 | #
|
124 | 127 | impl derive_more::core::str::FromStr for EnumNoFields {
|
125 | 128 | type Err = derive_more::FromStrError;
|
126 |
| - fn from_str(src: &str) -> Result<Self, derive_more::FromStrError> { |
127 |
| - Ok(match src.to_lowercase().as_str() { |
128 |
| - "foo" => EnumNoFields::Foo, |
129 |
| - "bar" => EnumNoFields::Bar, |
130 |
| - "baz" => EnumNoFields::Baz, |
| 129 | + fn from_str(s: &str) -> Result<Self, derive_more::FromStrError> { |
| 130 | + Ok(match s.to_lowercase().as_str() { |
| 131 | + "foo" => Self::Foo, |
| 132 | + "bar" => Self::Bar, |
| 133 | + "baz" if s == "Baz" => Self::Baz, |
| 134 | + "baz" if s == "BaZ" => Self::BaZ, |
131 | 135 | _ => return Err(derive_more::FromStrError::new("EnumNoFields")),
|
132 | 136 | })
|
133 | 137 | }
|
134 | 138 | }
|
135 | 139 | ```
|
| 140 | + |
| 141 | + |
| 142 | +### Empty structs |
| 143 | + |
| 144 | +Deriving `FromStr` for structs with no fields is similar to enums, |
| 145 | +but involves only case-insensitive matching by now. |
| 146 | + |
| 147 | +Given the following struct: |
| 148 | +```rust |
| 149 | +# use derive_more::FromStr; |
| 150 | +# |
| 151 | +#[derive(FromStr, Debug, Eq, PartialEq)] |
| 152 | +struct Foo; |
| 153 | + |
| 154 | +assert_eq!("foo".parse::<Foo>().unwrap(), Foo); |
| 155 | +assert_eq!("Foo".parse::<Foo>().unwrap(), Foo); |
| 156 | +assert_eq!("FOO".parse::<Foo>().unwrap(), Foo); |
| 157 | +``` |
| 158 | + |
| 159 | +Code like this is generated: |
| 160 | +```rust |
| 161 | +# struct Foo; |
| 162 | +# |
| 163 | +impl derive_more::core::str::FromStr for Foo { |
| 164 | + type Err = derive_more::FromStrError; |
| 165 | + fn from_str(s: &str) -> Result<Self, derive_more::FromStrError> { |
| 166 | + Ok(match s.to_lowercase().as_str() { |
| 167 | + "foo" => Self, |
| 168 | + _ => return Err(derive_more::FromStrError::new("Foo")), |
| 169 | + }) |
| 170 | + } |
| 171 | +} |
| 172 | +``` |
0 commit comments