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}