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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use serde_derive_internals::{ast, ast::Container as SerdeContainer, attr};
use crate::{attrs::TsifyContainerAttrs, error_tracker::ErrorTracker};
/// Data structure storing information about a type decorated with `#[derive(Tsify)]`.
/// This structure also keeps information that was parsed via Serde's macros.
pub struct Container<'a> {
/// Errors that occurred during processing.
pub errors: ErrorTracker,
/// Attributes passed to the `#[derive(Tsify)]` macro.
pub attrs: TsifyContainerAttrs,
/// Information about the type as parsed by Serde.
pub serde_container: SerdeContainer<'a>,
/// The `ident` of the type as written in the Rust code.
pub ident_str: String,
/// The name type that will be serialized to Typescript.
pub name: String,
}
impl<'a> Container<'a> {
pub fn new(serde_container: SerdeContainer<'a>) -> Self {
let input = &serde_container.original;
let attrs = TsifyContainerAttrs::from_derive_input(input);
let errors = ErrorTracker::new();
let attrs = match attrs {
Ok(attrs) => attrs,
Err(err) => {
errors.syn_error(err);
Default::default()
}
};
let name = attrs
.ty_config
.format_name(serde_container.attrs.name().serialize_name().to_string());
let ident_str = attrs
.ty_config
.format_name(serde_container.ident.to_string());
Self {
errors,
attrs,
serde_container,
ident_str,
name,
}
}
pub fn from_derive_input(input: &'a syn::DeriveInput) -> syn::Result<Self> {
let cx = serde_derive_internals::Ctxt::new();
let serde_cont =
SerdeContainer::from_ast(&cx, input, serde_derive_internals::Derive::Serialize);
match serde_cont {
Some(serde_container) => {
cx.check()?;
Ok(Self::new(serde_container))
}
None => Err(cx.check().expect_err("serde_cont is None")),
}
}
/// The `ident` of the type as written in the Rust code.
pub fn ident(&self) -> &syn::Ident {
&self.serde_container.ident
}
/// The `ident` of the type as written in the Rust code as a string.
pub fn ident_str(&self) -> String {
self.ident_str.clone()
}
#[inline]
pub fn serde_attrs(&self) -> &attr::Container {
&self.serde_container.attrs
}
/// Whether or not Serde has marked this type as `transparent`.
pub fn transparent(&self) -> bool {
self.serde_attrs().transparent()
}
/// The name of the type that will be serialized to Typescript.
pub fn name(&self) -> String {
self.name.clone()
}
/// Information about the generics associated with the type as parsed by Serde.
pub fn generics(&self) -> &syn::Generics {
self.serde_container.generics
}
/// Remove the default from every type parameter because in the generated impls
/// they look like associated types: "error: associated type bindings are not
/// allowed here".
pub fn generics_without_defaults(&self) -> syn::Generics {
let generics = self.generics();
syn::Generics {
params: generics
.params
.iter()
.map(|param| match param {
syn::GenericParam::Type(param) => syn::GenericParam::Type(syn::TypeParam {
eq_token: None,
default: None,
..param.clone()
}),
_ => param.clone(),
})
.collect(),
..generics.clone()
}
}
/// Information about the data fields of the type as parsed by Serde.
pub fn serde_data(&self) -> &ast::Data<'_> {
&self.serde_container.data
}
/// Add a new error to the list of processing errors.
pub fn syn_error(&self, err: syn::Error) {
self.errors.syn_error(err);
}
/// Return all accumulated errors.
pub fn check(self) -> syn::Result<()> {
self.errors.check()
}
}