more_convert_derive/
lib.rs

1macro_rules! use_internal {
2    ($internal:path, $input:ident) => {
3        $internal(syn::parse_macro_input!($input as syn::DeriveInput))
4            .unwrap_or_else(syn::Error::into_compile_error)
5            .into()
6    };
7}
8
9/// Automatically implements [`std::convert::From`] and [`std::convert::Into`] for repr on enums.
10///
11/// # Where to use:
12///  - Managing Type
13///  - Easy to understand constants
14///
15/// # Note:
16///  - require `#[repr(u8)]` or `#[repr(u16)]` or ...
17///  - default is require explicit
18///
19/// # Enum Attribute:
20///  - serde: automatically implements [`serde::Serialize`] and [`serde::Deserialize`]
21///  - implicit: make it less explicit
22///
23/// # Variant Attribute:
24///  ( Currency no. )
25///
26/// # Examples
27///
28/// ## Normal
29///
30/// ```rust
31/// use more_convert::EnumRepr;
32/// #[derive(EnumRepr, Clone, Copy, Debug, PartialEq)]
33/// #[repr(u8)]
34/// pub enum Test {
35///     Zero = 0,
36///     Three = 3,
37///     Four = 4,
38/// }
39///
40/// assert_eq!(0u8, Test::Zero.into());
41/// assert_eq!(3u8, Test::Three.into());
42/// assert_eq!(4u8, Test::Four.into());
43///
44/// assert_eq!(0u8.try_into(), Ok(Test::Zero));
45/// assert_eq!(3u8.try_into(), Ok(Test::Three));
46/// assert_eq!(4u8.try_into(), Ok(Test::Four));
47///
48/// assert_eq!(TryInto::<Test>::try_into(1u8).unwrap_err(), String::from("invalid Test: 1"));
49/// ```
50///
51/// ## serde
52///
53/// ```rust
54/// use more_convert::EnumRepr;
55/// #[derive(EnumRepr, Clone, Copy, Debug, PartialEq)]
56/// #[repr(u8)]
57/// #[enum_repr(serde)]
58/// pub enum Test {
59///     Zero = 0,
60///     Three = 3,
61///     Four = 4,
62/// }
63///
64///
65/// assert_eq!(serde_json::to_string(&Test::Zero).unwrap(), "0");
66/// assert_eq!(serde_json::to_string(&Test::Three).unwrap(), "3");
67/// assert_eq!(serde_json::to_string(&Test::Four).unwrap(), "4");
68///
69/// assert_eq!(serde_json::from_str::<Test>("0").unwrap(), Test::Zero);
70/// assert_eq!(serde_json::from_str::<Test>("3").unwrap(), Test::Three);
71/// assert_eq!(serde_json::from_str::<Test>("4").unwrap(), Test::Four);
72///
73/// assert_eq!(serde_json::from_str::<Test>("1").unwrap_err().to_string(), String::from("invalid Test: 1"));
74/// ```
75/// ## implicit
76///
77/// ```rust
78/// use more_convert::EnumRepr;
79/// #[derive(EnumRepr, Clone, Copy, Debug, PartialEq)]
80/// #[repr(u8)]
81/// #[enum_repr(implicit)]
82/// pub enum Test {
83///     Zero,
84///     Three = 3,
85///     Four,
86/// }
87///
88/// assert_eq!(0u8, Test::Zero.into());
89/// assert_eq!(3u8, Test::Three.into());
90/// assert_eq!(4u8, Test::Four.into());
91///
92/// assert_eq!(0u8.try_into(), Ok(Test::Zero));
93/// assert_eq!(3u8.try_into(), Ok(Test::Three));
94/// assert_eq!(4u8.try_into(), Ok(Test::Four));
95///
96/// assert_eq!(TryInto::<Test>::try_into(1u8).unwrap_err(), String::from("invalid Test: 1"));
97/// ```
98///
99#[proc_macro_derive(EnumRepr, attributes(enum_repr))]
100pub fn derive_enum_repr(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
101    use_internal!(more_convert_derive_internal::derive_enum_repr, input)
102}
103
104/// Automatically implements [`std::convert::From`] and [`std::convert::Into`] on structs.
105///
106/// # Who uses it:
107///   - When you are using the architectural
108///   - Those who find the implementation of from and into cumbersome.
109///
110/// # Struct Attribute:
111///   - into: `impl From<#self> for #into_struct { /* auto gen */}`
112///   - from: `impl From<#from_struct> for #self { /* auto gen */}`
113///   - from_into: impl from and into
114///
115/// # Field Attribute:
116///   - ignore: ignore this field
117///   - rename: rename this field
118///   - group of map: map this field (Choose one of these)
119///     > default: `#field_name.into()`
120///     - map: replace expr
121///     - map_field: Process and pass field data
122///     - map_struct: Create data from struct references
123///
124/// # Examples
125///
126/// ## Normal
127///
128/// ```rust
129/// use more_convert::Convert;
130/// #[derive(Convert)]
131/// #[convert(into(B))]
132/// pub struct A {
133///     pub normal: u8,
134///     // auto into of inner
135///     pub opt: Option<u8>,
136///     // auto into of inner
137///     pub vec: Vec<u8>,
138/// }
139///
140/// pub struct B {
141///     normal: u16,
142///     opt: Option<u16>,
143///     vec: Vec<u16>,
144/// }
145///
146/// let a = A {
147///     normal: 0u8,
148///     opt: Some(1u8),
149///     vec: vec![2u8, 3u8],
150/// };
151///
152/// let b: B = a.into();
153///
154/// assert_eq!(b.normal, 0u16);
155/// assert_eq!(b.opt, Some(1u16));
156/// assert_eq!(b.vec, vec![2u16, 3u16]);
157/// ```
158///
159/// ## Reanem
160///
161/// ```rust
162/// use more_convert::Convert;
163/// #[derive(Convert)]
164/// #[convert(into(B))]
165/// pub struct A {
166///     #[convert(rename = "sample")]
167///     hey: String,
168/// }
169///
170/// pub struct B {
171///     sample: String,
172/// }
173///
174/// let a = A {
175///     hey: "hello".to_string(),
176/// };
177///
178/// let b: B = a.into();
179///
180/// assert_eq!(b.sample, "hello");
181/// ```
182///
183/// ## Map
184///
185/// ```rust
186/// use more_convert::Convert;
187/// #[derive(Convert)]
188/// #[convert(into(B))]
189/// pub struct A {
190///     // value's type is `A`
191///     // The reason for the `value` is because of the From trait's args
192///     #[convert(map = value.map.to_string())]
193///     map: u8,
194///     #[convert(map_field = map_field)]
195///     map_field: u8,
196///     #[convert(map_struct = map_struct)]
197///     map_struct: u8,
198/// }
199///
200/// fn map_field(map_field: u8) -> String {
201///     map_field.to_string()
202/// }
203///
204/// fn map_struct(a: &A) -> String {
205///     a.map_struct.to_string()
206/// }
207///
208/// pub struct B {
209///     map: String,
210///     map_field: String,
211///     map_struct: String,
212/// }
213///
214/// let a = A {
215///     map: 1,
216///     map_field: 2,
217///     map_struct: 3,
218/// };
219///
220/// let b: B = a.into();
221///
222/// assert_eq!(b.map, "1");
223/// assert_eq!(b.map_field, "2");
224/// assert_eq!(b.map_struct, "3");
225/// ```
226///
227#[proc_macro_derive(Convert, attributes(convert))]
228pub fn derive_convert(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
229    use_internal!(more_convert_derive_internal::derive_convert, input)
230}
231
232/// Automatically implements [`more_convert::EnumName`] on enum
233///
234/// # Where to use:
235///   - Only want the kind
236///
237/// # Note:
238///   - prefix and suffix are applied after rename_all
239///
240/// # EnumAttribute:
241///   - rename_all: apply rule to field name
242///     - default is "none"
243///     - The possible values are ("lowercase", "UPPERCASE", "PascalCase", "camelCase",
244///       "snake_case", "SCREAMING_SNAKE_CASE", "kebab-case", "SCREAMING-KEBAB-CASE")
245///   - prefix: add prefix to field name
246///   - suffix: add suffix to field name
247///
248/// # Variant Attribute:
249///  - rename: rename field, (prefix, suffix and rename_all are not applied)
250///  - nest: call EnumName on the first field of the variant
251///
252/// # Examples
253///
254/// ## Normal
255///
256/// ```rust
257/// use more_convert::EnumName;
258///
259/// #[derive(EnumName)]
260/// pub enum Error {
261///   InvalidCode,
262///   ServerError,
263/// }
264///
265/// assert_eq!("InvalidCode", Error::InvalidCode.enum_name());
266/// assert_eq!("ServerError", Error::ServerError.enum_name());
267/// ```
268///
269/// ## rename and rename_all
270///
271/// ```rust
272/// use more_convert::EnumName;
273///
274/// #[derive(EnumName)]
275/// #[enum_name(rename_all = "snake_case")]
276/// pub enum Error {
277///   InvalidCode,
278///   ServerError,
279///   #[enum_name(rename = "NotFound")]
280///   NotFoundError,
281/// }
282///
283/// assert_eq!("invalid_code", Error::InvalidCode.enum_name());
284/// assert_eq!("server_error", Error::ServerError.enum_name());
285/// assert_eq!("NotFound", Error::NotFoundError.enum_name());
286/// ```
287///
288/// ## prefix and suffix
289/// ```rust
290/// use more_convert::EnumName;
291///
292/// #[derive(EnumName)]
293/// #[enum_name(prefix = "Error", suffix  = "What")]
294/// pub enum Error {
295///  InvalidCode,
296///  ServerError,
297/// }
298///
299/// assert_eq!("ErrorInvalidCodeWhat", Error::InvalidCode.enum_name());
300/// assert_eq!("ErrorServerErrorWhat", Error::ServerError.enum_name());
301/// ```
302///
303/// ## nest
304/// ```rust
305/// use more_convert::EnumName;
306///
307/// use more_convert::EnumName;
308///
309/// #[derive(EnumName)]
310/// #[enum_name(prefix = "Inner")]
311/// pub enum Inner {
312///     A,
313///     B,
314/// }
315///
316/// #[derive(EnumName)]
317/// pub enum TestEnumName {
318///     InvalidCode,
319///
320///     #[enum_name(nest)]
321///     Inner(Inner),
322/// }
323///
324/// assert_eq!("InvalidCode", TestEnumName::InvalidCode.enum_name());
325///
326/// assert_eq!("InnerA", Inner::A.enum_name());
327/// assert_eq!("InnerB", Inner::B.enum_name());
328/// ```
329///
330#[proc_macro_derive(EnumName, attributes(enum_name))]
331pub fn derive_enum_name(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
332    use_internal!(more_convert_derive_internal::derive_enum_name, input)
333}