devise_core/
mapper.rs

1use proc_macro2::TokenStream;
2
3use crate::{Result, Field, Fields, Variant, Struct, Enum, Input};
4
5// used by the macros.
6type FnOutput = TokenStream;
7
8pub trait Mapper {
9    trait_method!(map_input: Input<'_>, input_default);
10    trait_method!(map_struct: Struct<'_>, struct_default);
11    trait_method!(map_enum: Enum<'_>, enum_default);
12    trait_method!(map_variant: Variant<'_>, variant_default);
13    trait_method!(map_fields: Fields<'_>, fields_default);
14    trait_method!(map_field: Field<'_>, field_default);
15}
16
17impl<M: Mapper + ?Sized> Mapper for &mut M {
18    trait_forward!(<M as Mapper>::map_input: Input<'_>);
19    trait_forward!(<M as Mapper>::map_struct: Struct<'_>);
20    trait_forward!(<M as Mapper>::map_enum: Enum<'_>);
21    trait_forward!(<M as Mapper>::map_variant: Variant<'_>);
22    trait_forward!(<M as Mapper>::map_fields: Fields<'_>);
23    trait_forward!(<M as Mapper>::map_field: Field<'_>);
24}
25
26impl Mapper for TokenStream {
27    fn map_input(&mut self, _: Input<'_>) -> Result<FnOutput> {
28        Ok(self.clone())
29    }
30}
31
32#[derive(Default)]
33pub struct MapperBuild {
34    output_mapper: function!(TokenStream),
35    input_mapper: function!(Input<'_>),
36    struct_mapper: function!(Struct<'_>),
37    enum_mapper: function!(Enum<'_>),
38    variant_mapper: function!(Variant<'_>),
39    fields_mapper: function!(Fields<'_>),
40    field_mapper: function!(Field<'_>),
41}
42
43impl MapperBuild {
44    pub fn new() -> Self {
45        MapperBuild::default()
46    }
47
48    builder!(with_output: TokenStream, output_mapper);
49    try_builder!(try_with_output: TokenStream, output_mapper);
50
51    builder!(input_map: Input<'_>, input_mapper);
52    try_builder!(try_input_map: Input<'_>, input_mapper);
53
54    builder!(struct_map: Struct<'_>, struct_mapper);
55    try_builder!(try_struct_map: Struct<'_>, struct_mapper);
56
57    builder!(enum_map: Enum<'_>, enum_mapper);
58    try_builder!(try_enum_map: Enum<'_>, enum_mapper);
59
60    builder!(variant_map: Variant<'_>, variant_mapper);
61    try_builder!(try_variant_map: Variant<'_>, variant_mapper);
62
63    builder!(fields_map: Fields<'_>, fields_mapper);
64    try_builder!(try_fields_map: Fields<'_>, fields_mapper);
65
66    builder!(field_map: Field<'_>, field_mapper);
67    try_builder!(try_field_map: Field<'_>, field_mapper);
68}
69
70impl Mapper for MapperBuild {
71    fn map_input(&mut self, value: Input<'_>) -> Result<TokenStream> {
72        let output = match self.input_mapper.take() {
73            Some(mut m) => {
74                let result = m(self, value);
75                self.input_mapper = Some(m);
76                result?
77            }
78            None => input_default(&mut *self, value)?
79        };
80
81        match self.output_mapper.take() {
82            Some(mut m) => {
83                let result = m(self, output);
84                self.output_mapper = Some(m);
85                result
86            }
87            _ => Ok(output)
88        }
89    }
90
91    builder_forward!(map_struct: Struct<'_>, struct_mapper, struct_default);
92    builder_forward!(map_enum: Enum<'_>, enum_mapper, enum_default);
93    builder_forward!(map_variant: Variant<'_>, variant_mapper, variant_default);
94    builder_forward!(map_fields: Fields<'_>, fields_mapper, fields_default);
95    builder_forward!(map_field: Field<'_>, field_mapper, field_default);
96}
97
98pub fn input_default<M: Mapper>(mut mapper: M, value: Input<'_>) -> Result<TokenStream> {
99    match value {
100        Input::Struct(v) => mapper.map_struct(v),
101        Input::Enum(v) => mapper.map_enum(v),
102        Input::Union(_) => unimplemented!("union mapping is unimplemented")
103    }
104}
105
106pub fn enum_default<M: Mapper>(mut mapper: M, value: Enum<'_>) -> Result<TokenStream> {
107    let variant = value.variants().map(|v| &v.inner.ident);
108    let fields = value.variants().map(|v| v.fields().match_tokens());
109    let enum_name = ::std::iter::repeat(value.parent.ident());
110    let expression = value.variants()
111        .map(|v| mapper.map_variant(v))
112        .collect::<Result<Vec<_>>>()?;
113
114    Ok(quote! {
115        // FIXME: Check if we can also use id_match_tokens due to match
116        // ergonomics. I don't think so, though. If we can't, then ask (in
117        // `function`) whether receiver is `&self`, `&mut self` or `self` and
118        // bind match accordingly.
119        match self {
120            #(#enum_name::#variant #fields => { #expression }),*
121        }
122    })
123}
124
125pub fn struct_default<M: Mapper>(mut mapper: M, value: Struct) -> Result<TokenStream> {
126    mapper.map_fields(value.fields())
127}
128
129pub fn variant_default<M: Mapper>(mut mapper: M, value: Variant) -> Result<TokenStream> {
130    mapper.map_fields(value.fields())
131}
132
133pub fn fields_null<M: Mapper>(mut mapper: M, value: Fields) -> Result<TokenStream> {
134    let field = value.iter()
135        .map(|field| mapper.map_field(field))
136        .collect::<Result<Vec<_>>>()?;
137
138    Ok(quote!(#(#field)*))
139}
140
141pub fn fields_default<M: Mapper>(mut mapper: M, value: Fields) -> Result<TokenStream> {
142    let field = value.iter()
143        .map(|field| mapper.map_field(field))
144        .collect::<Result<Vec<_>>>()?;
145
146    Ok(quote!({ #(#field)* }))
147}
148
149pub fn field_default<M: Mapper>(_: M, _: Field) -> Result<TokenStream> {
150    Ok(TokenStream::new())
151}
152
153pub fn enum_null<M: Mapper>(mut mapper: M, value: Enum<'_>) -> Result<TokenStream> {
154    let expression = value.variants()
155        .map(|v| mapper.map_variant(v))
156        .collect::<Result<Vec<_>>>()?;
157
158    Ok(quote!(#(#expression)*))
159}