mod alias;
mod common;
mod enums;
mod native;
mod structs;
pub use alias::*;
pub use common::*;
pub use enums::*;
pub use native::*;
pub use structs::*;
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum Type<Id> {
Enum(Enum<Id>),
Struct(Struct<Id>),
UnitStruct(UnitStruct),
TupleStruct(TupleStruct<Id>),
NewtypeStruct(NewtypeStruct<Id>),
TypeAlias(TypeAlias<Id>),
Native(Native<Id>),
Option(Id),
Box(Id),
Vec(Id),
Map(Id, Id),
Set(Id),
Array(Id, usize),
Tuple(Vec<Id>),
Unit,
Boolean,
Integer(String),
Float(String),
String,
JsonValue,
Never,
}
macro_rules! all_named_types {
(_) => {
$crate::build::Type::Enum(_)
| $crate::build::Type::Struct(_)
| $crate::build::Type::UnitStruct(_)
| $crate::build::Type::TupleStruct(_)
| $crate::build::Type::NewtypeStruct(_)
| $crate::build::Type::TypeAlias(_)
};
($common:ident) => {
all_named_types!(@ident $common; $common)
};
(@ident common; $common:ident) => {
$crate::build::Type::Enum($crate::build::Enum {
$common,
..
})
| $crate::build::Type::Struct($crate::build::Struct {
$common,
..
})
| $crate::build::Type::UnitStruct($crate::build::UnitStruct {
$common,
..
})
| $crate::build::Type::TupleStruct($crate::build::TupleStruct {
$common,
..
})
| $crate::build::Type::NewtypeStruct($crate::build::NewtypeStruct {
$common,
..
})
| $crate::build::Type::TypeAlias($crate::build::TypeAlias {
$common,
..
})
};
}
pub(crate) use all_named_types;
impl<Id> Type<Id> {
pub fn name(&self) -> Option<&str> {
self.common().and_then(|common| common.name())
}
pub fn default(&self) -> Option<&serde_json::Value> {
self.common().and_then(|common| common.default())
}
pub fn set_default(&mut self, default: Option<JsonValue>) {
if let Some(common) = self.common_mut() {
common.default = default;
}
}
pub fn extra_derives(&self) -> &[String] {
self.common()
.map_or(&[] as &[String], |common| common.extra_derives())
}
pub fn extra_attrs(&self) -> &[String] {
self.common()
.map_or(&[] as &[String], |common| common.extra_attrs())
}
pub(crate) fn common(&self) -> Option<&TypeCommon> {
match self {
all_named_types!(common) => Some(common),
_ => None,
}
}
pub(crate) fn common_mut(&mut self) -> Option<&mut TypeCommon> {
match self {
all_named_types!(common) => Some(common),
_ => None,
}
}
}
pub(crate) struct ContainedChild<Id> {
pub(crate) relation: crate::error::Relation,
pub(crate) id: Id,
pub(crate) optional: bool,
}
impl<Id> ContainedChild<Id> {
fn required(relation: crate::error::Relation, id: Id) -> Self {
Self {
relation,
id,
optional: false,
}
}
fn optional(relation: crate::error::Relation, id: Id) -> Self {
Self {
relation,
id,
optional: true,
}
}
}
impl<Id: Clone + Ord + std::fmt::Debug + std::fmt::Display> Type<Id> {
pub fn children(&self) -> Vec<Id> {
match self {
Type::Enum(type_enum) => type_enum.children(),
Type::Struct(type_struct) => type_struct.children(),
Type::UnitStruct(_) => Vec::new(),
Type::TupleStruct(type_tuple_struct) => type_tuple_struct.children(),
Type::NewtypeStruct(type_newtype_struct) => type_newtype_struct.children(),
Type::TypeAlias(alias_info) => alias_info.children(),
Type::Boolean => Vec::new(),
Type::String => Vec::new(),
Type::Native(native) => native.parameters().to_vec(),
Type::Option(id)
| Type::Box(id)
| Type::Vec(id)
| Type::Set(id)
| Type::Array(id, _) => vec![id.clone()],
Type::Map(key_id, value_id) => vec![key_id.clone(), value_id.clone()],
Type::Tuple(items) => items.clone(),
Type::Unit => Vec::new(),
Type::Integer(_) => Vec::new(),
Type::Float(_) => Vec::new(),
Type::JsonValue => Vec::new(),
Type::Never => Vec::new(),
}
}
pub fn children_with_context(&self) -> Vec<(Id, String)> {
match self {
Type::Enum(type_enum) => type_enum
.variants
.iter()
.flat_map(|variant| match &variant.details {
VariantDetails::Unit => Vec::new(),
VariantDetails::Item(id) => {
vec![(id.clone(), variant.rust_name.clone())]
}
VariantDetails::Tuple(items) => items
.iter()
.enumerate()
.map(|(ii, id)| (id.clone(), format!("{}.{}", variant.rust_name, ii)))
.collect::<Vec<_>>(),
VariantDetails::Struct(items) => items
.iter()
.map(|prop| {
(
prop.type_id.clone(),
format!("{}.{}", variant.rust_name, prop.rust_name),
)
})
.collect::<Vec<_>>(),
})
.collect::<Vec<_>>(),
Type::Struct(type_struct) => type_struct
.properties
.iter()
.map(
|StructProperty {
rust_name, type_id, ..
}| (type_id.clone(), rust_name.to_string()),
)
.collect::<Vec<_>>(),
Type::UnitStruct(_) => Vec::new(),
Type::TupleStruct(type_tuple_struct) => {
let mut children = type_tuple_struct
.fields
.iter()
.cloned()
.enumerate()
.map(|(ii, type_id)| (type_id, ii.to_string()))
.collect::<Vec<_>>();
if let Some(rest) = &type_tuple_struct.rest {
children.push((rest.clone(), type_tuple_struct.fields.len().to_string()));
}
children
}
Type::NewtypeStruct(NewtypeStruct { inner, .. }) => {
vec![(inner.clone(), "inner".to_string())]
}
Type::TypeAlias(TypeAlias { .. }) => Vec::new(),
Type::Native(_) => Vec::new(),
Type::Option(id) | Type::Box(id) => vec![(id.clone(), "".to_string())],
Type::Vec(id) | Type::Set(id) | Type::Array(id, _) => {
vec![(id.clone(), "item".to_string())]
}
Type::Map(key_id, value_id) => vec![
(key_id.clone(), "key".to_string()),
(value_id.clone(), "value".to_string()),
],
Type::Tuple(items) => items
.iter()
.enumerate()
.map(|(ii, id)| (id.clone(), ii.to_string()))
.collect::<Vec<_>>(),
Type::Unit
| Type::Boolean
| Type::Integer(_)
| Type::Float(_)
| Type::String
| Type::JsonValue
| Type::Never => Vec::new(),
}
}
pub fn contained_children_mut(&mut self) -> Vec<&mut Id> {
match self {
Type::Enum(Enum { variants, .. }) => {
let mut out = Vec::new();
for variant in variants {
match &mut variant.details {
VariantDetails::Unit => {}
VariantDetails::Item(schema_ref) => {
out.push(schema_ref);
}
VariantDetails::Tuple(schema_refs) => {
out.extend(schema_refs);
}
VariantDetails::Struct(props) => {
for StructProperty { type_id, .. } in props {
out.push(type_id);
}
}
}
}
out
}
Type::Struct(Struct { properties, .. }) => properties
.iter_mut()
.map(|prop| &mut prop.type_id)
.collect(),
Type::UnitStruct(_) => vec![],
Type::TupleStruct(type_tuple_struct) => type_tuple_struct.contained_children_mut(),
Type::NewtypeStruct(type_newtype_struct) => {
type_newtype_struct.contained_children_mut()
}
Type::TypeAlias(alias_info) => {
vec![&mut alias_info.target]
}
Type::Option(id) => vec![id],
Type::Array(id, _) => vec![id],
Type::Tuple(items) => items.iter_mut().collect(),
Type::Native(_) => Default::default(),
Type::Box(_)
| Type::Vec(_)
| Type::Map(_, _)
| Type::Set(_)
| Type::Unit
| Type::Boolean
| Type::Integer(_)
| Type::Float(_)
| Type::String
| Type::JsonValue
| Type::Never => Default::default(),
}
}
pub(crate) fn contained_children_related(&self) -> Vec<ContainedChild<Id>> {
use crate::error::Relation;
match self {
Type::Enum(Enum { variants, .. }) => {
let mut out = Vec::new();
for variant in variants {
let relation = variant.relation();
match &variant.details {
VariantDetails::Unit => {}
VariantDetails::Item(id) => {
out.push(ContainedChild::required(relation.clone(), id.clone()))
}
VariantDetails::Tuple(ids) => {
out.extend(
ids.iter().map(|id| {
ContainedChild::required(relation.clone(), id.clone())
}),
);
}
VariantDetails::Struct(props) => {
out.extend(props.iter().map(|prop| {
if prop.state.is_optional() {
ContainedChild::optional(relation.clone(), prop.type_id.clone())
} else {
ContainedChild::required(relation.clone(), prop.type_id.clone())
}
}));
}
}
}
out
}
Type::Struct(Struct { properties, .. }) => properties
.iter()
.map(|prop| {
let relation = Relation::Field(prop.rust_name.to_string());
let id = prop.type_id.clone();
if prop.state.is_optional() {
ContainedChild::optional(relation, id)
} else {
ContainedChild::required(relation, id)
}
})
.collect(),
Type::UnitStruct(_) => Vec::new(),
Type::TupleStruct(TupleStruct { fields, rest, .. }) => {
let mut out = fields
.iter()
.map(|id| ContainedChild::required(Relation::Element, id.clone()))
.collect::<Vec<_>>();
if let Some(rest) = rest {
out.push(ContainedChild::required(Relation::Element, rest.clone()));
}
out
}
Type::NewtypeStruct(NewtypeStruct { inner, .. }) => {
vec![ContainedChild::required(Relation::Inner, inner.clone())]
}
Type::TypeAlias(alias_info) => {
vec![ContainedChild::required(
Relation::Target,
alias_info.target.clone(),
)]
}
Type::Option(id) => vec![ContainedChild::required(Relation::Element, id.clone())],
Type::Array(id, _) => vec![ContainedChild::required(Relation::Element, id.clone())],
Type::Tuple(items) => items
.iter()
.map(|id| ContainedChild::required(Relation::Element, id.clone()))
.collect(),
Type::Native(_) => Vec::new(),
Type::Box(_)
| Type::Vec(_)
| Type::Map(_, _)
| Type::Set(_)
| Type::Unit
| Type::Boolean
| Type::Integer(_)
| Type::Float(_)
| Type::String
| Type::JsonValue
| Type::Never => Vec::new(),
}
}
pub fn is_named(&self) -> bool {
matches!(self, all_named_types!(_))
}
pub(crate) fn validate_built(&self) -> Result<(), crate::error::Error<Id>> {
match self {
Type::Enum(type_enum) => type_enum.validate(),
Type::Struct(type_struct) => type_struct.validate(),
Type::UnitStruct(unit_struct) => unit_struct.validate(),
Type::TupleStruct(tuple_struct) => tuple_struct.validate(),
Type::NewtypeStruct(newtype_struct) => newtype_struct.validate(),
Type::TypeAlias(type_alias) => type_alias.validate(),
Type::Native(native) => native.validate(),
_ => Ok(()),
}
}
}