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