#![allow(clippy::return_self_not_must_use)]
use super::*;
use std::iter::IntoIterator;
macro_rules! unwrap_opt {
( $builder:ident, $optional_field:ident ) => {{
let unwrapped = $builder.$optional_field.clone().expect(&format!(
"
```````````````````````````````````````````````
Builder is not finished because the value of the
field `{}` is not set.
Builder: `{:?}`\n
```````````````````````````````````````````````
",
stringify!($optional_field),
&$builder,
));
unwrapped
}};
}
pub fn decl<'a>(d: &'a mut Declarations, name: &'static str) -> TypeDeclarationBuilder<'a> {
TypeDeclarationBuilder {
d,
name,
docs: "",
value: None,
config: vec![build_derives(vec![
"serde::Serialize",
"serde::Deserialize",
"Debug",
"Clone",
])],
generic_params: vec![],
}
}
#[derive(Debug)]
pub struct TypeDeclarationBuilder<'a> {
d: &'a mut Declarations,
name: &'static str,
docs: &'static str,
value: Option<DeclarationValue>,
config: Vec<TypeDeclarationConfig>,
generic_params: Vec<TGeneric>,
}
impl<'a> TypeDeclarationBuilder<'a> {
pub fn value<T: Into<DeclarationValue>>(mut self, value: T) -> Self {
self.value = Some(value.into());
self
}
pub fn build(self) -> TReference {
self.d.add(TypeDeclaration {
name: self.name,
docs: self.docs,
value: unwrap_opt!(self, value),
config: self.config,
generic_params: self.generic_params,
})
}
}
impl From<TStruct> for DeclarationValue {
fn from(s: TStruct) -> Self {
DeclarationValue::TStruct(s)
}
}
impl From<TEnum> for DeclarationValue {
fn from(s: TEnum) -> Self {
DeclarationValue::TEnum(s)
}
}
pub fn build_struct() -> TStructBuilder {
TStructBuilder { fields: vec![] }
}
#[derive(Debug, Clone)]
pub struct TStructBuilder {
pub fields: Vec<StructField>,
}
impl TStructBuilder {
pub fn build(self) -> TStruct {
TStruct {
fields: self.fields,
}
}
}
impl TStructBuilder {
pub fn field(mut self, f: StructField) -> Self {
self.fields.push(f);
self
}
pub fn fields(self, fields: impl IntoIterator<Item = StructField>) -> Self {
let mut s = self;
for f in fields {
s = s.field(f)
}
s
}
}
impl TStruct {
pub fn decl(self) -> DeclarationValue {
DeclarationValue::TStruct(self)
}
}
pub fn build_struct_field(name: &'static str) -> StructFieldBuilder {
StructFieldBuilder {
name,
..Default::default()
}
}
#[derive(Default, Debug)]
pub struct StructFieldBuilder {
name: &'static str,
pub docs: &'static str,
pub field_type: Option<StructFieldType>,
pub config: Vec<StructFieldConfig>,
}
impl StructFieldBuilder {
pub fn build(self) -> StructField {
StructField {
name: self.name,
docs: self.docs,
field_type: unwrap_opt!(self, field_type),
config: self.config,
}
}
pub fn field_type<T: Into<StructFieldType>>(mut self, t: T) -> Self {
self.field_type = Some(t.into());
self
}
pub fn optional(mut self) -> Self {
let field_type = self
.field_type
.expect("must set field type before making it optional");
let field_type = match field_type {
StructFieldType::TMap(map) => StructFieldType::TOption(TOption::TMap(map)),
StructFieldType::TSet(set) => StructFieldType::TOption(TOption::TSet(set)),
StructFieldType::TOption(opt) => StructFieldType::TOption(opt),
StructFieldType::TPrimitive(p) => StructFieldType::TOption(TOption::TPrimitive(p)),
StructFieldType::TTuple(t) => StructFieldType::TOption(TOption::TTuple(t)),
StructFieldType::TVec(v) => StructFieldType::TOption(TOption::TVec(v)),
};
self.field_type = Some(field_type);
self
}
}
impl From<TPrimitive> for StructFieldType {
fn from(p: TPrimitive) -> Self {
StructFieldType::TPrimitive(p)
}
}
impl From<TVec> for StructFieldType {
fn from(v: TVec) -> Self {
StructFieldType::TVec(v)
}
}
impl From<TMap> for StructFieldType {
fn from(v: TMap) -> Self {
StructFieldType::TMap(v)
}
}
impl From<TSet> for StructFieldType {
fn from(v: TSet) -> Self {
StructFieldType::TSet(v)
}
}
impl From<TReference> for StructFieldType {
fn from(v: TReference) -> Self {
StructFieldType::TPrimitive(v.primitive())
}
}
pub fn build_enum() -> TEnumBuilder {
TEnumBuilder { variants: vec![] }
}
pub struct TEnumBuilder {
variants: Vec<EnumVariant>,
}
impl TEnumBuilder {
pub fn build(self) -> TEnum {
TEnum {
variants: self.variants,
}
}
pub fn variant(mut self, v: EnumVariant) -> Self {
self.variants.push(v);
self
}
pub fn variants(self, variants: impl IntoIterator<Item = EnumVariant>) -> Self {
let mut s = self;
for v in variants {
s = s.variant(v)
}
s
}
}
pub fn build_enum_variant(name: &'static str) -> EnumVariantBuilder {
EnumVariantBuilder {
name,
docs: "",
variant_type: None,
}
}
#[derive(Debug)]
pub struct EnumVariantBuilder {
pub name: &'static str,
pub docs: &'static str,
pub variant_type: Option<EnumVariantType>,
}
impl EnumVariantBuilder {
pub fn build(self) -> EnumVariant {
EnumVariant {
name: self.name,
docs: self.docs,
variant_type: unwrap_opt!(self, variant_type),
}
}
pub fn variant_type<T: Into<EnumVariantType>>(mut self, t: T) -> Self {
self.variant_type = Some(t.into());
self
}
}
impl From<TPrimitive> for EnumVariantType {
fn from(p: TPrimitive) -> Self {
EnumVariantType::TPrimitive(p)
}
}
impl From<TReference> for EnumVariantType {
fn from(p: TReference) -> Self {
EnumVariantType::TPrimitive(p.primitive())
}
}
impl From<TStruct> for EnumVariantType {
fn from(s: TStruct) -> Self {
EnumVariantType::TStruct(s)
}
}
pub fn build_vec<T: Into<TPrimitive>>(t: T) -> TVec {
TVec::TPrimitive(t.into())
}
pub fn build_map<K: Into<TPrimitive>, V: Into<TPrimitive>>(k: K, v: V) -> TMap {
TMap {
key: k.into(),
value: TMapValue::TPrimitive(v.into()),
t: TMapType::BTree,
}
}
pub fn build_set<T: Into<TPrimitive>>(t: T) -> TSet {
TSet::TPrimitive(t.into())
}
impl From<TReference> for TPrimitive {
fn from(t: TReference) -> Self {
t.primitive()
}
}
pub fn build_derives(derives: Vec<&str>) -> TypeDeclarationConfig {
let derives = derives
.iter()
.map(|s| s.to_string())
.collect::<Vec<_>>()
.join(", ");
let s = Box::leak(format!("#[derive({})]", derives).into_boxed_str());
TypeDeclarationConfig::RustAttribute(s)
}