add_macro_impl_into/
lib.rs

1extern crate proc_macro;
2use proc_macro::TokenStream;
3use venial::{ parse_item, Item };
4
5pub(crate) mod error;
6pub(crate) mod tools;
7pub(crate) mod prelude;     use prelude::*;
8mod impl_enum;              use impl_enum::impl_into_enum;
9mod impl_struct;            use impl_struct::impl_into_struct;
10
11/// This macros provides the implementation of trait [Into<T>](std::convert::Into) (writed for crate [add_macro](https://docs.rs/add_macro))
12/// 
13/// # Examples:
14/// ```
15/// use add_macro_impl_into::Into;
16///
17/// #[derive(Debug, PartialEq)]
18/// struct User {
19///     name: String,
20///     subname: Option<String>,
21///     age: u8
22/// }
23///
24/// #[derive(Debug, Clone, Into)]
25/// #[into("User" = "User { name: self.name, subname: None, age: self.age }")]
26/// #[into("String" = "format!(\"name: {}, age: {}\", self.name, self.age)")]
27/// struct Person {
28///     name: String,
29///     age: u8
30/// }
31///
32/// fn main() {
33///     let bob = Person {
34///         name: "Bob".to_owned(),
35///         age: 22
36///     };
37///
38///     let bob_user: User = bob.clone().into();
39///     assert_eq!(
40///         bob_user,
41///         User {
42///             name: "Bob".to_owned(),
43///             subname: None,
44///             age: 22
45///         }
46///     );
47///
48///     let bob_str: String = bob.into();
49///     assert_eq!(bob_str, "name: Bob, age: 22");
50/// }
51/// ```
52/// ```
53/// use add_macro_impl_into::Into;
54///
55/// #[derive(Debug, PartialEq)]
56/// struct Cat;
57///
58/// #[derive(Debug, PartialEq)]
59/// struct Dog;
60///
61/// #[derive(Debug, PartialEq)]
62/// struct Bird;
63///
64/// #[derive(Debug, PartialEq)]
65/// struct Python;
66///
67/// #[derive(Debug, PartialEq, Into)]
68/// #[into("String" = "format!(\"Animal::{self:?}\")")]
69/// #[into("Option<Cat>" = "if let Self::Cat(v) = self { Some(v) }else{ None }")]
70/// enum Animal {
71///     Cat(Cat),
72///
73///     #[into]
74///     Dog(Dog),   // Option<Dog>
75/// 
76///     #[into = "if let Self::Bird(value) = self { value }else{ panic!(\"It's not a dog.\") }"]
77///     // #[into("if let Self::Bird(value) = self { value }else{ panic!(\"It's not a dog.\") }")]
78///     Bird(Bird),
79/// 
80///     #[into("Option<Python>" = "if let Self::Python(v) = self { Some(v) }else{ None }")]
81///     #[into("Python" = "Into::<Option<Python>>::into(self).expect(\"It's not a Python\")")]
82///     Python(Python),
83/// }
84///
85/// fn main() {
86///     let cat_str: String = Animal::Cat(Cat {}).into();
87///     assert_eq!(cat_str, "Animal::Cat(Cat)");
88/// 
89///     let cat: Option<Cat> = Animal::Cat(Cat {}).into();
90///     assert_eq!(cat, Some(Cat {}));
91/// 
92///     let dog: Option<Dog> = Animal::Dog(Dog {}).into();
93///     assert_eq!(dog, Some(Dog {}));
94///
95///     let bird: Bird = Animal::Bird(Bird {}).into();
96///     assert_eq!(bird, Bird {});
97///
98///     let python: Option<Python> = Animal::Python(Python {}).into();
99///     assert_eq!(python, Some(Python {}));
100///
101///     let python: Python = Animal::Python(Python {}).into();
102///     assert_eq!(python, Python {});
103/// }
104/// ```
105#[proc_macro_derive(Into, attributes(into))]
106pub fn derive_into(input: TokenStream) -> TokenStream {
107    let item = parse_item(input.into()).unwrap();
108    
109    match item {
110        Item::Enum(data) => match impl_into_enum(data) {
111            Ok(output) => output.into(),
112            Err(e) => panic!("{e}")
113        },
114
115        Item::Struct(data) => match impl_into_struct(data) {
116            Ok(output) => output.into(),
117            Err(e) => panic!("{e}")
118        },
119
120        _ => panic!("{}", Error::ImplementationError)
121    }
122}