1use crate::prelude::{marker::PhantomData, vec::Vec};
126
127use crate::{
128 form::{Form, MetaForm, PortableForm},
129 Field, MetaType, Path, Type, TypeDef, TypeDefComposite, TypeDefVariant, TypeInfo,
130 TypeParameter, Variant,
131};
132
133pub mod state {
135 pub enum PathNotAssigned {}
137 pub enum PathAssigned {}
139}
140
141#[must_use]
143pub struct TypeBuilder<F: Form = MetaForm, S = state::PathNotAssigned> {
144 path: Option<Path<F>>,
145 type_params: Vec<TypeParameter<F>>,
146 docs: Vec<F::String>,
147 marker: PhantomData<fn() -> (F, S)>,
148}
149
150impl<F: Form, S> Default for TypeBuilder<F, S> {
151 fn default() -> Self {
152 TypeBuilder {
153 path: Default::default(),
154 type_params: Default::default(),
155 docs: Default::default(),
156 marker: Default::default(),
157 }
158 }
159}
160
161impl<F: Form> TypeBuilder<F, state::PathNotAssigned> {
162 pub fn path(self, path: Path<F>) -> TypeBuilder<F, state::PathAssigned> {
164 TypeBuilder {
165 path: Some(path),
166 type_params: self.type_params,
167 docs: self.docs,
168 marker: Default::default(),
169 }
170 }
171}
172
173impl<F: Form> TypeBuilder<F, state::PathAssigned> {
174 fn build<D>(self, type_def: D) -> Type<F>
175 where
176 D: Into<TypeDef<F>>,
177 {
178 let path = self.path.expect("Path not assigned");
179 Type::new(path, self.type_params, type_def, self.docs)
180 }
181
182 pub fn variant(self, builder: Variants<F>) -> Type<F> {
184 self.build(builder.finalize())
185 }
186
187 pub fn composite<T>(self, fields: FieldsBuilder<F, T>) -> Type<F> {
189 self.build(TypeDefComposite::new(fields.finalize()))
190 }
191}
192
193impl<F: Form, S> TypeBuilder<F, S> {
194 pub fn type_params<I>(mut self, type_params: I) -> Self
196 where
197 I: IntoIterator<Item = TypeParameter<F>>,
198 {
199 self.type_params = type_params.into_iter().collect();
200 self
201 }
202}
203
204impl<S> TypeBuilder<PortableForm, S> {
205 #[cfg(feature = "docs")]
206 pub fn docs_portable<I>(mut self, docs: I) -> Self
208 where
209 I: IntoIterator<Item = <PortableForm as Form>::String>,
210 {
211 self.docs = docs.into_iter().collect();
212 self
213 }
214}
215
216impl<S> TypeBuilder<MetaForm, S> {
217 #[cfg(feature = "docs")]
218 pub fn docs(mut self, docs: &[&'static str]) -> Self {
220 self.docs = docs.to_vec();
221 self
222 }
223
224 #[cfg(not(feature = "docs"))]
225 #[inline]
226 pub fn docs(self, _docs: &'static [&'static str]) -> Self {
228 self
229 }
230
231 pub fn docs_always(mut self, docs: &[&'static str]) -> Self {
233 self.docs = docs.to_vec();
234 self
235 }
236}
237
238pub enum NoFields {}
240pub enum NamedFields {}
242pub enum UnnamedFields {}
244
245pub struct Fields<F: Form>(PhantomData<fn() -> F>);
247
248impl<F: Form> Fields<F> {
249 pub fn unit() -> FieldsBuilder<F, NoFields> {
251 FieldsBuilder::<F, NoFields>::default()
252 }
253
254 pub fn named() -> FieldsBuilder<F, NamedFields> {
256 FieldsBuilder::default()
257 }
258
259 pub fn unnamed() -> FieldsBuilder<F, UnnamedFields> {
261 FieldsBuilder::default()
262 }
263}
264
265#[must_use]
267pub struct FieldsBuilder<F: Form, T> {
268 fields: Vec<Field<F>>,
269 marker: PhantomData<fn() -> T>,
270}
271
272impl<F: Form, T> Default for FieldsBuilder<F, T> {
273 fn default() -> Self {
274 Self {
275 fields: Vec::new(),
276 marker: Default::default(),
277 }
278 }
279}
280
281impl<F: Form, T> FieldsBuilder<F, T> {
282 pub fn finalize(self) -> Vec<Field<F>> {
284 self.fields
285 }
286}
287
288impl<T> FieldsBuilder<MetaForm, T> {
289 fn push_field(mut self, field: Field) -> Self {
290 if !field.ty.is_phantom() {
292 self.fields.push(field);
293 }
294 self
295 }
296}
297
298impl FieldsBuilder<MetaForm, NamedFields> {
299 pub fn field<B>(self, builder: B) -> Self
301 where
302 B: Fn(
303 FieldBuilder,
304 )
305 -> FieldBuilder<MetaForm, field_state::NameAssigned, field_state::TypeAssigned>,
306 {
307 let builder = builder(FieldBuilder::new());
308 self.push_field(builder.finalize())
309 }
310}
311
312impl FieldsBuilder<MetaForm, UnnamedFields> {
313 pub fn field<B>(self, builder: B) -> Self
315 where
316 B: Fn(
317 FieldBuilder,
318 )
319 -> FieldBuilder<MetaForm, field_state::NameNotAssigned, field_state::TypeAssigned>,
320 {
321 let builder = builder(FieldBuilder::new());
322 self.push_field(builder.finalize())
323 }
324}
325
326impl<T> FieldsBuilder<PortableForm, T> {
327 fn push_field(mut self, field: Field<PortableForm>) -> Self {
328 self.fields.push(field);
329 self
330 }
331}
332
333impl FieldsBuilder<PortableForm, NamedFields> {
334 pub fn field_portable<B>(self, builder: B) -> Self
336 where
337 B: Fn(
338 FieldBuilder<PortableForm, field_state::NameNotAssigned, field_state::TypeNotAssigned>,
339 )
340 -> FieldBuilder<PortableForm, field_state::NameAssigned, field_state::TypeAssigned>,
341 {
342 let builder = builder(FieldBuilder::new());
343 self.push_field(builder.finalize())
344 }
345}
346
347impl FieldsBuilder<PortableForm, UnnamedFields> {
348 pub fn field_portable<B>(self, builder: B) -> Self
350 where
351 B: Fn(
352 FieldBuilder<PortableForm, field_state::NameNotAssigned, field_state::TypeNotAssigned>,
353 ) -> FieldBuilder<
354 PortableForm,
355 field_state::NameNotAssigned,
356 field_state::TypeAssigned,
357 >,
358 {
359 let builder = builder(FieldBuilder::new());
360 self.push_field(builder.finalize())
361 }
362}
363
364pub mod field_state {
366 pub enum NameNotAssigned {}
368 pub enum NameAssigned {}
370 pub enum TypeNotAssigned {}
372 pub enum TypeAssigned {}
374}
375
376#[must_use]
378pub struct FieldBuilder<
379 F: Form = MetaForm,
380 N = field_state::NameNotAssigned,
381 T = field_state::TypeNotAssigned,
382> {
383 name: Option<F::String>,
384 ty: Option<F::Type>,
385 type_name: Option<F::String>,
386 docs: Vec<F::String>,
387 marker: PhantomData<fn() -> (N, T)>,
388}
389
390impl<F: Form, N, T> Default for FieldBuilder<F, N, T> {
391 fn default() -> Self {
392 FieldBuilder {
393 name: Default::default(),
394 ty: Default::default(),
395 type_name: Default::default(),
396 docs: Default::default(),
397 marker: Default::default(),
398 }
399 }
400}
401
402impl<F: Form> FieldBuilder<F> {
403 pub fn new() -> Self {
405 Default::default()
406 }
407}
408
409impl<F: Form, T> FieldBuilder<F, field_state::NameNotAssigned, T> {
410 pub fn name(self, name: F::String) -> FieldBuilder<F, field_state::NameAssigned, T> {
412 FieldBuilder {
413 name: Some(name),
414 ty: self.ty,
415 type_name: self.type_name,
416 docs: self.docs,
417 marker: PhantomData,
418 }
419 }
420}
421
422impl<N> FieldBuilder<MetaForm, N, field_state::TypeNotAssigned> {
423 pub fn ty<TY>(self) -> FieldBuilder<MetaForm, N, field_state::TypeAssigned>
425 where
426 TY: TypeInfo + 'static + ?Sized,
427 {
428 FieldBuilder {
429 name: self.name,
430 ty: Some(MetaType::new::<TY>()),
431 type_name: self.type_name,
432 docs: self.docs,
433 marker: PhantomData,
434 }
435 }
436
437 pub fn compact<TY>(self) -> FieldBuilder<MetaForm, N, field_state::TypeAssigned>
439 where
440 TY: scale::HasCompact + TypeInfo + 'static,
441 {
442 FieldBuilder {
443 name: self.name,
444 ty: Some(MetaType::new::<scale::Compact<TY>>()),
445 type_name: self.type_name,
446 docs: self.docs,
447 marker: PhantomData,
448 }
449 }
450}
451
452impl<N> FieldBuilder<PortableForm, N, field_state::TypeNotAssigned> {
453 pub fn ty<T>(self, ty: T) -> FieldBuilder<PortableForm, N, field_state::TypeAssigned>
455 where
456 T: Into<<PortableForm as Form>::Type>,
457 {
458 FieldBuilder {
459 name: self.name,
460 ty: Some(ty.into()),
461 type_name: self.type_name,
462 docs: self.docs,
463 marker: PhantomData,
464 }
465 }
466}
467
468impl<F: Form, N, T> FieldBuilder<F, N, T> {
469 pub fn type_name(self, type_name: F::String) -> FieldBuilder<F, N, T> {
471 FieldBuilder {
472 name: self.name,
473 ty: self.ty,
474 type_name: Some(type_name),
475 docs: self.docs,
476 marker: PhantomData,
477 }
478 }
479}
480
481impl<N, T> FieldBuilder<PortableForm, N, T> {
482 #[cfg(feature = "docs")]
483 pub fn docs_portable<I>(mut self, docs: I) -> Self
485 where
486 I: IntoIterator<Item = <PortableForm as Form>::String>,
487 {
488 self.docs = docs.into_iter().collect();
489 self
490 }
491}
492
493impl<N, T> FieldBuilder<MetaForm, N, T> {
494 #[cfg(feature = "docs")]
495 pub fn docs(self, docs: &'static [&'static str]) -> Self {
497 FieldBuilder {
498 name: self.name,
499 ty: self.ty,
500 type_name: self.type_name,
501 docs: docs.to_vec(),
502 marker: PhantomData,
503 }
504 }
505
506 #[cfg(not(feature = "docs"))]
507 #[inline]
508 pub fn docs(self, _docs: &'static [&'static str]) -> Self {
510 self
511 }
512
513 pub fn docs_always(self, docs: &'static [&'static str]) -> Self {
516 FieldBuilder {
517 name: self.name,
518 ty: self.ty,
519 type_name: self.type_name,
520 docs: docs.to_vec(),
521 marker: PhantomData,
522 }
523 }
524}
525
526impl<F: Form, N> FieldBuilder<F, N, field_state::TypeAssigned> {
527 pub fn finalize(self) -> Field<F> {
529 Field::new(
530 self.name,
531 self.ty.expect("Type should be set by builder"),
532 self.type_name,
533 self.docs,
534 )
535 }
536}
537
538#[derive(Default)]
540#[must_use]
541pub struct Variants<F: Form = MetaForm> {
542 variants: Vec<Variant<F>>,
543}
544
545impl<F: Form> Variants<F> {
546 pub fn new() -> Self {
548 Self {
549 variants: Vec::new(),
550 }
551 }
552
553 pub fn variant<B>(mut self, name: F::String, builder: B) -> Self
555 where
556 B: Fn(VariantBuilder<F>) -> VariantBuilder<F, variant_state::IndexAssigned>,
557 {
558 let builder = builder(VariantBuilder::new(name));
559 self.variants.push(builder.finalize());
560 self
561 }
562
563 pub fn variant_unit(mut self, name: F::String, index: u8) -> Self {
565 let builder = VariantBuilder::new(name).index(index);
566 self.variants.push(builder.finalize());
567 self
568 }
569
570 pub fn finalize(self) -> TypeDefVariant<F> {
572 TypeDefVariant::new(self.variants)
573 }
574}
575
576pub mod variant_state {
578 pub enum IndexNotAssigned {}
580 pub enum IndexAssigned {}
582}
583
584#[must_use]
586pub struct VariantBuilder<F: Form, S = variant_state::IndexNotAssigned> {
587 name: F::String,
588 index: Option<u8>,
589 fields: Vec<Field<F>>,
590 discriminant: Option<u64>,
591 docs: Vec<F::String>,
592 marker: PhantomData<S>,
593}
594
595impl<F: Form> VariantBuilder<F, variant_state::IndexNotAssigned> {
596 pub fn new(name: F::String) -> Self {
598 Self {
599 name,
600 fields: Vec::new(),
601 discriminant: None,
602 index: None,
603 docs: Vec::new(),
604 marker: Default::default(),
605 }
606 }
607
608 pub fn index(self, index: u8) -> VariantBuilder<F, variant_state::IndexAssigned> {
610 VariantBuilder {
611 name: self.name,
612 index: Some(index),
613 fields: self.fields,
614 discriminant: self.discriminant,
615 docs: self.docs,
616 marker: Default::default(),
617 }
618 }
619}
620
621impl<F: Form, S> VariantBuilder<F, S> {
622 pub fn discriminant(mut self, discriminant: u64) -> Self {
624 self.discriminant = Some(discriminant);
625 self
626 }
627
628 pub fn fields<T>(mut self, fields_builder: FieldsBuilder<F, T>) -> Self {
630 self.fields = fields_builder.finalize();
631 self
632 }
633}
634
635impl<S> VariantBuilder<PortableForm, S> {
636 #[cfg(feature = "docs")]
637 pub fn docs_portable<I>(mut self, docs: I) -> Self
639 where
640 I: IntoIterator<Item = <PortableForm as Form>::String>,
641 {
642 self.docs = docs.into_iter().collect();
643 self
644 }
645}
646
647impl<S> VariantBuilder<MetaForm, S> {
648 #[cfg(feature = "docs")]
649 pub fn docs(mut self, docs: &[&'static str]) -> Self {
651 self.docs = docs.to_vec();
652 self
653 }
654
655 #[cfg(not(feature = "docs"))]
656 #[inline]
657 pub fn docs(self, _docs: &[&'static str]) -> Self {
659 self
660 }
661
662 pub fn docs_always(mut self, docs: &[&'static str]) -> Self {
665 self.docs = docs.to_vec();
666 self
667 }
668}
669
670impl<F: Form> VariantBuilder<F, variant_state::IndexAssigned> {
671 pub fn finalize(self) -> Variant<F> {
673 Variant::new(
674 self.name,
675 self.fields,
676 self.index.expect("Index should be assigned by the builder"),
677 self.docs,
678 )
679 }
680}