1use alloc::{string::String, vec::Vec};
2
3use sails_idl_ast::{
4 Annotation, EnumDef, EnumVariant, StructDef, StructField, Type, TypeDecl, TypeDef,
5 TypeParameter,
6};
7
8#[derive(Debug, Clone)]
10pub struct FieldBuilder<P> {
11 parent: P,
12 name: Option<String>,
13 metadata: Metadata,
14}
15
16#[derive(Debug, Clone)]
18pub struct VariantBuilder {
19 parent: VariantDefBuilder,
20 name: String,
21 metadata: Metadata,
22 fields: Vec<StructField>,
23}
24
25#[derive(Debug, Clone)]
27pub struct CompositeBuilder {
28 type_builder: TypeBuilder,
29 fields: Vec<StructField>,
30}
31
32#[derive(Debug, Clone)]
34pub struct VariantDefBuilder {
35 type_builder: TypeBuilder,
36 variants: Vec<EnumVariant>,
37}
38
39#[derive(Debug, Clone)]
41pub struct ParamBuilder {
42 inner: TypeBuilder,
43 param_name: String,
44}
45
46#[derive(Debug, Clone, Default)]
48pub struct TypeBuilder {
49 name: String,
50 type_params: Vec<TypeParameter>,
51 metadata: Metadata,
52}
53
54#[derive(Debug, Clone, Default)]
55struct Metadata {
56 docs: Vec<String>,
57 annotations: Vec<Annotation>,
58}
59
60pub trait PushField: Sized {
62 fn push_field(&mut self, field: StructField);
64}
65
66impl<P: PushField> FieldBuilder<P> {
67 pub fn ty(mut self, type_decl: TypeDecl) -> P {
69 self.parent.push_field(StructField {
70 name: self.name,
71 type_decl,
72 docs: self.metadata.docs,
73 annotations: self.metadata.annotations,
74 });
75 self.parent
76 }
77}
78
79impl<P> FieldBuilder<P> {
80 pub fn doc(mut self, doc: impl Into<String>) -> Self {
82 self.metadata.doc(doc);
83 self
84 }
85
86 pub fn annotate(mut self, name: impl Into<String>) -> Self {
88 self.metadata.annotate(name);
89 self
90 }
91
92 pub fn value(mut self, value: impl Into<String>) -> Self {
94 self.metadata.value(value);
95 self
96 }
97}
98
99impl VariantBuilder {
100 pub fn field(self, name: impl Into<String>) -> FieldBuilder<Self> {
102 FieldBuilder {
103 parent: self,
104 name: Some(name.into()),
105 metadata: Metadata::default(),
106 }
107 }
108
109 pub fn unnamed(self) -> FieldBuilder<Self> {
111 FieldBuilder {
112 parent: self,
113 name: None,
114 metadata: Metadata::default(),
115 }
116 }
117
118 pub fn doc(mut self, doc: impl Into<String>) -> Self {
120 self.metadata.doc(doc);
121 self
122 }
123
124 pub fn annotate(mut self, name: impl Into<String>) -> Self {
126 self.metadata.annotate(name);
127 self
128 }
129
130 pub fn value(mut self, value: impl Into<String>) -> Self {
132 self.metadata.value(value);
133 self
134 }
135
136 pub fn finish_variant(mut self) -> VariantDefBuilder {
138 self.parent.variants.push(EnumVariant {
139 name: self.name,
140 def: StructDef {
141 fields: self.fields,
142 },
143 entry_id: 0,
144 docs: self.metadata.docs,
145 annotations: self.metadata.annotations,
146 });
147 self.parent
148 }
149}
150
151impl CompositeBuilder {
152 pub fn field(self, name: impl Into<String>) -> FieldBuilder<Self> {
154 FieldBuilder {
155 parent: self,
156 name: Some(name.into()),
157 metadata: Metadata::default(),
158 }
159 }
160
161 pub fn unnamed(self) -> FieldBuilder<Self> {
163 FieldBuilder {
164 parent: self,
165 name: None,
166 metadata: Metadata::default(),
167 }
168 }
169
170 pub fn doc(mut self, doc: impl Into<String>) -> Self {
172 self.type_builder.metadata.doc(doc);
173 self
174 }
175
176 pub fn annotate(mut self, name: impl Into<String>) -> Self {
178 self.type_builder.metadata.annotate(name);
179 self
180 }
181
182 pub fn value(mut self, value: impl Into<String>) -> Self {
184 self.type_builder.metadata.value(value);
185 self
186 }
187
188 pub fn build(self) -> Type {
190 self.type_builder.build(TypeDef::Struct(StructDef {
191 fields: self.fields,
192 }))
193 }
194}
195
196impl VariantDefBuilder {
197 pub fn add_variant(self, name: impl Into<String>) -> VariantBuilder {
199 VariantBuilder {
200 parent: self,
201 name: name.into(),
202 metadata: Metadata::default(),
203 fields: Vec::new(),
204 }
205 }
206
207 pub fn build(self) -> Type {
209 self.type_builder.build(TypeDef::Enum(EnumDef {
210 variants: self.variants,
211 }))
212 }
213}
214
215impl ParamBuilder {
216 pub fn default_ty(mut self, type_decl: TypeDecl) -> TypeBuilder {
218 self.inner.type_params.push(TypeParameter {
219 name: self.param_name,
220 ty: Some(type_decl),
221 });
222 self.inner
223 }
224
225 pub fn no_default(mut self) -> TypeBuilder {
227 self.inner.type_params.push(TypeParameter {
228 name: self.param_name,
229 ty: None,
230 });
231 self.inner
232 }
233}
234
235impl TypeBuilder {
236 pub fn new() -> Self {
238 Self::default()
239 }
240
241 pub fn name(mut self, name: impl Into<String>) -> Self {
243 self.name = name.into();
244 self
245 }
246
247 pub fn param(mut self, name: impl Into<String>) -> Self {
249 self.type_params.push(TypeParameter {
250 name: name.into(),
251 ty: None,
252 });
253 self
254 }
255
256 pub fn param_with_default(mut self, name: impl Into<String>, type_decl: TypeDecl) -> Self {
258 self.type_params.push(TypeParameter {
259 name: name.into(),
260 ty: Some(type_decl),
261 });
262 self
263 }
264
265 pub fn doc(mut self, doc: impl Into<String>) -> Self {
267 self.metadata.doc(doc);
268 self
269 }
270
271 pub fn annotate(mut self, name: impl Into<String>) -> Self {
273 self.metadata.annotate(name);
274 self
275 }
276
277 pub fn value(mut self, value: impl Into<String>) -> Self {
279 self.metadata.value(value);
280 self
281 }
282
283 pub fn composite(self) -> CompositeBuilder {
285 CompositeBuilder {
286 type_builder: self,
287 fields: Vec::new(),
288 }
289 }
290
291 pub fn variant(self) -> VariantDefBuilder {
293 VariantDefBuilder {
294 type_builder: self,
295 variants: Vec::new(),
296 }
297 }
298
299 pub fn alias(self, target: TypeDecl) -> Type {
301 self.build(TypeDef::Alias(sails_idl_ast::AliasDef { target }))
302 }
303
304 fn build(self, def: TypeDef) -> Type {
305 Type {
306 name: self.name,
307 type_params: self.type_params,
308 def,
309 docs: self.metadata.docs,
310 annotations: self.metadata.annotations,
311 }
312 }
313}
314
315impl Metadata {
316 fn doc(&mut self, doc: impl Into<String>) {
317 self.docs.push(doc.into());
318 }
319
320 fn annotate(&mut self, name: impl Into<String>) {
321 self.annotations.push((name.into(), None));
322 }
323
324 fn value(&mut self, value: impl Into<String>) {
325 if let Some(ann) = self.annotations.last_mut() {
326 ann.1 = Some(value.into());
327 }
328 }
329}
330
331impl PushField for CompositeBuilder {
332 fn push_field(&mut self, field: StructField) {
333 self.fields.push(field);
334 }
335}
336
337impl PushField for VariantBuilder {
338 fn push_field(&mut self, field: StructField) {
339 self.fields.push(field);
340 }
341}