123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- extern crate proc_macro;
- use proc_macro::TokenStream;
- use syn::{parse, parse_macro_input, DeriveInput, ItemImpl};
- use args::{Casts, Flag, Targets};
- use gen_caster::generate_caster;
- mod args;
- mod gen_caster;
- mod item_impl;
- mod item_type;
- /// Attached on an `impl` item or type definition, registers traits as targets for casting.
- ///
- /// If on an `impl` item, no argument is allowed. But on a type definition, the target traits
- /// must be listed explicitly.
- ///
- /// Add `[sync]` before the list of traits if the underlying type is `Sync + Send` and you
- /// need `std::sync::Arc`.
- ///
- /// # Examples
- /// ## On a trait impl
- /// ```
- /// use intertrait::*;
- ///
- /// struct Data;
- ///
- /// trait Greet {
- /// fn greet(&self);
- /// }
- ///
- /// // Greet can be cast into from any sub-trait of CastFrom implemented by Data.
- /// #[cast_to]
- /// impl Greet for Data {
- /// fn greet(&self) {
- /// println!("Hello");
- /// }
- /// }
- /// ```
- ///
- /// ## On a type definition
- /// Use when a target trait is derived or implemented in an external crate.
- /// ```
- /// use intertrait::*;
- ///
- /// // Debug can be cast into from any sub-trait of CastFrom implemented by Data
- /// #[cast_to(std::fmt::Debug)]
- /// #[derive(std::fmt::Debug)]
- /// struct Data;
- /// ```
- ///
- /// ## For Arc
- /// Use when the underlying type is `Sync + Send` and you want to use `Arc`.
- /// ```
- /// use intertrait::*;
- ///
- /// // Debug can be cast into from any sub-trait of CastFrom implemented by Data
- /// #[cast_to([sync] std::fmt::Debug)]
- /// #[derive(std::fmt::Debug)]
- /// struct Data;
- /// ```
- #[proc_macro_attribute]
- pub fn cast_to(args: TokenStream, input: TokenStream) -> TokenStream {
- match parse::<Targets>(args) {
- Ok(Targets { flags, paths }) => {
- if paths.is_empty() {
- item_impl::process(&flags, parse_macro_input!(input as ItemImpl))
- } else {
- item_type::process(&flags, paths, parse_macro_input!(input as DeriveInput))
- }
- }
- Err(err) => vec![err.to_compile_error(), input.into()]
- .into_iter()
- .collect(),
- }
- .into()
- }
- /// Declares target traits for casting implemented by a type.
- ///
- /// This macro is for registering both a concrete type and its traits to be targets for casting.
- /// Useful when the type definition and the trait implementations are in an external crate.
- ///
- /// **Note**: this macro cannot be used in an expression or statement prior to Rust 1.45.0,
- /// due to [a previous limitation](https://github.com/rust-lang/rust/pull/68717).
- /// If you want to use it in an expression or statement, use Rust 1.45.0 or later.
- ///
- /// # Examples
- /// ```
- /// use intertrait::*;
- ///
- /// #[derive(std::fmt::Debug)]
- /// enum Data {
- /// A, B, C
- /// }
- /// trait Greet {
- /// fn greet(&self);
- /// }
- /// impl Greet for Data {
- /// fn greet(&self) {
- /// println!("Hello");
- /// }
- /// }
- ///
- /// castable_to! { Data => std::fmt::Debug, Greet }
- ///
- /// # fn main() {}
- /// ```
- ///
- /// When the type is `Sync + Send` and is used with `Arc`:
- /// ```
- /// use intertrait::*;
- ///
- /// #[derive(std::fmt::Debug)]
- /// enum Data {
- /// A, B, C
- /// }
- /// trait Greet {
- /// fn greet(&self);
- /// }
- /// impl Greet for Data {
- /// fn greet(&self) {
- /// println!("Hello");
- /// }
- /// }
- /// castable_to! { Data => [sync] std::fmt::Debug, Greet }
- ///
- /// # fn main() {}
- /// ```
- #[proc_macro]
- pub fn castable_to(input: TokenStream) -> TokenStream {
- let Casts {
- ty,
- targets: Targets { flags, paths },
- } = parse_macro_input!(input);
- paths
- .iter()
- .map(|t| generate_caster(&ty, t, flags.contains(&Flag::Sync)))
- .collect::<proc_macro2::TokenStream>()
- .into()
- }
|