Skip to main content

conjure_codegen/
aliases.rs

1// Copyright 2018 Palantir Technologies, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14use proc_macro2::TokenStream;
15use quote::quote;
16
17use crate::context::{BaseModule, Context};
18use crate::types::objects::AliasDefinition;
19
20pub fn generate(ctx: &Context, def: &AliasDefinition) -> TokenStream {
21    let name = ctx.type_name(def.type_name().name());
22    let alias = ctx.rust_type(BaseModule::Objects, def.type_name(), def.alias());
23    let result = ctx.result_ident(def.type_name());
24    let docs = ctx.docs(def.docs());
25
26    let mut type_attrs = vec![quote!(#[serde(crate = "conjure_object::serde", transparent)])];
27    let mut field_attrs = vec![];
28    let mut derives = vec![
29        "Debug",
30        "Clone",
31        "conjure_object::serde::Deserialize",
32        "conjure_object::serde::Serialize",
33    ];
34
35    if ctx.is_copy(def.alias()) {
36        derives.push("Copy");
37    }
38
39    if ctx.is_double(def.alias()) {
40        derives.push("conjure_object::private::DeriveWith");
41        type_attrs.push(quote!(#[derive_with(PartialEq, Eq, PartialOrd, Ord, Hash)]));
42        field_attrs.push(quote!(#[derive_with(with = conjure_object::private::DoubleWrapper)]));
43    } else {
44        derives.push("PartialEq");
45        derives.push("Eq");
46        derives.push("PartialOrd");
47        derives.push("Ord");
48        derives.push("Hash");
49    }
50
51    if ctx.is_default(def.alias()) {
52        derives.push("Default");
53    }
54
55    let derives = derives.iter().map(|s| s.parse::<TokenStream>().unwrap());
56    // The derive attr has to be before the derive_with attr, so insert rather than push
57    type_attrs.insert(0, quote!(#[derive(#(#derives),*)]));
58
59    let display = if ctx.is_display(def.alias()) {
60        quote! {
61            impl std::fmt::Display for #name {
62                fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63                    std::fmt::Display::fmt(&self.0, fmt)
64                }
65            }
66        }
67    } else {
68        quote!()
69    };
70
71    let plain = if ctx.is_plain(def.alias()) {
72        quote! {
73            impl conjure_object::Plain for #name {
74                fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75                    conjure_object::Plain::fmt(&self.0, fmt)
76                }
77            }
78
79            impl conjure_object::FromPlain for #name {
80                type Err = <#alias as conjure_object::FromPlain>::Err;
81
82                #[inline]
83                fn from_plain(s: &str) -> #result<#name, Self::Err> {
84                    conjure_object::FromPlain::from_plain(s).map(#name)
85                }
86            }
87        }
88    } else {
89        quote!()
90    };
91
92    let from_iterator = match ctx.is_from_iter(BaseModule::Objects, def.type_name(), def.alias()) {
93        Some(item) => quote! {
94            impl std::iter::FromIterator<#item> for #name {
95                fn from_iter<T>(iter: T) -> Self
96                where
97                    T: std::iter::IntoIterator<Item = #item>,
98                {
99                    #name(std::iter::FromIterator::from_iter(iter))
100                }
101            }
102        },
103        None => quote!(),
104    };
105
106    let dealiased_type = ctx.rust_type(
107        BaseModule::Objects,
108        def.type_name(),
109        ctx.dealiased_type(def.alias()),
110    );
111
112    quote! {
113        #docs
114        #(#type_attrs)*
115        pub struct #name(#(#field_attrs)* pub #alias);
116
117        #display
118
119        #plain
120
121        #from_iterator
122
123        impl std::convert::From<#dealiased_type> for #name {
124            #[inline]
125            fn from(v: #dealiased_type) -> Self {
126                #name(std::convert::From::from(v))
127            }
128        }
129
130        impl std::ops::Deref for #name {
131            type Target = #alias;
132
133            #[inline]
134            fn deref(&self) -> &#alias {
135                &self.0
136            }
137        }
138
139        impl std::ops::DerefMut for #name {
140            #[inline]
141            fn deref_mut(&mut self) -> &mut #alias {
142                &mut self.0
143            }
144        }
145
146        impl std::convert::AsRef<#dealiased_type> for #name {
147            #[inline]
148            fn as_ref(&self) -> &#dealiased_type {
149                &self.0
150            }
151        }
152    }
153}