intercom_common/attributes/
type_info.rs

1use crate::prelude::*;
2
3/// Expands the `ForeignType` derive attribute.
4///
5/// The attribute expansion results in the following items:
6///
7/// - Implementation of the ForeignType trait.
8pub fn expand_bidirectional_type_info(
9    item_tokens: TokenStreamNightly,
10) -> Result<TokenStreamNightly, syn::Error>
11{
12    // Get the name of the type we want to implement the trait for.
13    let input: syn::DeriveInput = syn::parse(item_tokens)?;
14    let name = &input.ident;
15
16    // Immpl requires the the generics in particular way.
17    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
18    let result = quote! { impl #impl_generics intercom::type_system::ForeignType for #name #ty_generics #where_clause {
19
20        /// The default name is the name of the type.
21        fn type_name() -> &'static str { stringify!( #name ) }
22    } };
23
24    Ok(result.into())
25}
26
27/// Expands the `ExternType` derive attribute.
28///
29/// The attribute expansion results in the following items:
30///
31/// - Implementation of the ExternType trait.
32pub fn expand_derive_extern_type(
33    item_tokens: TokenStreamNightly,
34) -> Result<TokenStreamNightly, syn::Error>
35{
36    // Get the name of the type we want to implement the trait for.
37    let input: syn::DeriveInput = syn::parse(item_tokens)?;
38    let name = &input.ident;
39
40    // Immpl requires the the generics in particular way.
41    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
42    let result = quote! {
43        impl<TS: intercom::type_system::TypeSystem> #impl_generics intercom::type_system::ExternType<TS> for #name #ty_generics #where_clause {
44            type ForeignType = #name;
45        }
46    };
47
48    Ok(result.into())
49}
50
51/// Expands the `ExternInput` derive attribute.
52///
53/// The attribute expansion results in the following items:
54///
55/// - Implementation of the ExternInput trait.
56pub fn expand_derive_extern_input(
57    item_tokens: TokenStreamNightly,
58) -> Result<TokenStreamNightly, syn::Error>
59{
60    // Get the name of the type we want to implement the trait for.
61    let input: syn::DeriveInput = syn::parse(item_tokens)?;
62    let name = &input.ident;
63
64    // Immpl requires the the generics in particular way.
65    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
66    let result = quote! {
67        unsafe impl<TS: intercom::type_system::TypeSystem> #impl_generics intercom::type_system::ExternInput<TS> for #name #ty_generics #where_clause {
68
69            type Lease = ();
70
71            #[inline(always)]
72            unsafe fn into_foreign_parameter(self) -> intercom::ComResult<(Self::ForeignType, Self::Lease)> {
73                Ok((self, ()))
74            }
75
76            type Owned = #name;
77
78            #[inline(always)]
79            unsafe fn from_foreign_parameter(source: Self::ForeignType) -> intercom::ComResult<Self::Owned> {
80                Ok(source)
81            }
82        }
83
84        unsafe impl<TS: intercom::type_system::TypeSystem> #impl_generics intercom::type_system::InfallibleExternInput<TS> for #name #ty_generics #where_clause {
85
86            type Lease = ();
87
88            #[inline(always)]
89            unsafe fn into_foreign_parameter(self) -> (Self::ForeignType, Self::Lease) {
90                (self, ())
91            }
92
93            type Owned = #name;
94
95            #[inline(always)]
96            unsafe fn from_foreign_parameter(source: Self::ForeignType) -> Self::Owned {
97                source
98            }
99        }
100    };
101
102    Ok(result.into())
103}
104
105/// Expands the `ExternOutput` derive attribute.
106///
107/// The attribute expansion results in the following items:
108///
109/// - Implementation of the ExternOutput trait.
110pub fn expand_derive_extern_output(
111    item_tokens: TokenStreamNightly,
112) -> Result<TokenStreamNightly, syn::Error>
113{
114    // Get the name of the type we want to implement the trait for.
115    let input: syn::DeriveInput = syn::parse(item_tokens)?;
116    let name = &input.ident;
117
118    // Impl requires the the generics in particular way.
119    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
120    let result = quote! {
121        unsafe impl<TS: intercom::type_system::TypeSystem> #impl_generics intercom::type_system::ExternOutput<TS> for #name #ty_generics #where_clause {
122
123            #[inline(always)]
124            fn into_foreign_output(self) -> intercom::ComResult<Self::ForeignType> {
125                Ok(self)
126            }
127
128            #[inline(always)]
129            unsafe fn from_foreign_output(source: Self::ForeignType) -> intercom::ComResult<Self> {
130                Ok(source)
131            }
132        }
133
134        unsafe impl<TS: intercom::type_system::TypeSystem> #impl_generics intercom::type_system::InfallibleExternOutput<TS> for #name #ty_generics #where_clause {
135
136            #[inline(always)]
137            fn into_foreign_output(self) -> Self::ForeignType {
138                self
139            }
140
141            #[inline(always)]
142            unsafe fn from_foreign_output(source: Self::ForeignType) -> Self {
143                source
144            }
145        }
146    };
147
148    Ok(result.into())
149}