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
mod wrapper; use proc_macro::TokenStream; use syn::{DeriveInput, parse_macro_input}; /// ``` /// use dmutils_derive::wrapper; /// use dmutils::*; /// /// #[derive(Clone)] /// struct NewPoint { /// x: f64, /// y: f64, /// } /// /// // the following two lines can be changed to /// // `type Point = std::sync::Arc<NewPoint>` /// // and the test still pass. /// // This enables you to switch between "value type" /// // and "reference type" without too many rewrites. /// #[wrapper(ptr)] /// struct Point(NewPoint); /// /// let mut p: Point = NewPoint { /// x: 2.0, /// y: -1.5, /// }.into(); /// /// assert_eq!(p.x, 2.0); /// assert_eq!(p.y, -1.5); /// /// p.mutate().x = 0.3; /// assert_eq!(p.x, 0.3); /// assert_eq!(p.y, -1.5); /// ``` /// /// ``` /// use dmutils_derive::wrapper; /// use dmutils::*; /// use std::convert::TryFrom; /// /// // misu = Make Illegal State Unpresentable /// #[wrapper(misu)] /// pub struct Pos(i32); /// impl TryFrom<i32> for Pos { /// type Error = String; /// /// fn try_from(value: i32) -> Result<Self, Self::Error> { /// if value > 0 { /// Ok(Pos(value)) /// } else { /// Err(format!("'{}' is not positive", value)) /// } /// } /// } /// /// let pos = Pos::try_from(2).unwrap(); /// let _ref = pos.as_ref(); /// let _ref = &*pos; /// let _back_to_primitive: i32 = pos.into(); #[proc_macro_attribute] pub fn wrapper(attr: TokenStream, item: TokenStream) -> TokenStream { let derive_input = parse_macro_input!(item as DeriveInput); wrapper::new(attr, derive_input) .unwrap_or_else(|e| e.to_compile_error()) .into() }