use std::{
borrow::{Borrow, Cow},
fmt::Display,
};
mod r#enum;
mod fields;
mod list;
mod literal;
mod map;
mod named;
mod primitive;
pub mod reference;
mod r#struct;
mod tuple;
pub use fields::*;
pub use list::*;
pub use literal::*;
pub use map::*;
pub use named::*;
pub use primitive::*;
pub use r#enum::*;
pub use r#struct::*;
pub use tuple::*;
use crate::SpectaID;
#[derive(Debug, Clone, PartialEq)]
pub enum DataType {
Any,
Unknown,
Primitive(PrimitiveType),
Literal(LiteralType),
List(List),
Map(Map),
Nullable(Box<DataType>),
Struct(StructType),
Enum(EnumType),
Tuple(TupleType),
Result(Box<(DataType, DataType)>),
Reference(DataTypeReference),
Generic(GenericType),
}
impl DataType {
pub fn generics(&self) -> Option<&Vec<GenericType>> {
match self {
Self::Struct(s) => Some(s.generics()),
Self::Enum(e) => Some(e.generics()),
_ => None,
}
}
pub fn to_named(self, name: impl Into<Cow<'static, str>>) -> NamedDataType {
NamedDataType {
name: name.into(),
docs: Cow::Borrowed(""),
deprecated: None,
ext: None,
inner: self,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum DeprecatedType {
Deprecated,
DeprecatedWithSince {
since: Option<Cow<'static, str>>,
note: Cow<'static, str>,
},
}
#[derive(Debug, Clone, PartialEq)]
pub struct DataTypeReference {
pub(crate) name: Cow<'static, str>,
pub(crate) sid: SpectaID,
pub(crate) generics: Vec<(GenericType, DataType)>,
}
impl DataTypeReference {
pub fn name(&self) -> &Cow<'static, str> {
&self.name
}
pub fn sid(&self) -> SpectaID {
self.sid
}
pub fn generics(&self) -> &Vec<(GenericType, DataType)> {
&self.generics
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct GenericType(pub(crate) Cow<'static, str>);
impl Display for GenericType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
impl Borrow<str> for GenericType {
fn borrow(&self) -> &str {
&self.0
}
}
impl From<Cow<'static, str>> for GenericType {
fn from(value: Cow<'static, str>) -> Self {
Self(value)
}
}
impl From<GenericType> for DataType {
fn from(t: GenericType) -> Self {
Self::Generic(t)
}
}
impl<T: Into<DataType> + 'static> From<Vec<T>> for DataType {
fn from(t: Vec<T>) -> Self {
DataType::Enum(EnumType {
name: "Vec".into(),
sid: None,
repr: EnumRepr::Untagged,
skip_bigint_checks: false,
variants: t
.into_iter()
.map(|t| {
let ty: DataType = t.into();
(
match &ty {
DataType::Struct(s) => s.name.clone(),
DataType::Enum(e) => e.name().clone(),
_ => "".into(),
},
EnumVariant {
skip: false,
docs: Cow::Borrowed(""),
deprecated: None,
inner: EnumVariants::Unnamed(UnnamedFields {
fields: vec![Field {
optional: false,
flatten: false,
deprecated: None,
docs: Cow::Borrowed(""),
ty: Some(ty),
}],
}),
},
)
})
.collect(),
generics: vec![],
})
}
}
impl<T: Into<DataType> + 'static> From<Option<T>> for DataType {
fn from(t: Option<T>) -> Self {
t.map(Into::into)
.unwrap_or_else(|| LiteralType::None.into())
}
}
impl<'a> From<&'a str> for DataType {
fn from(t: &'a str) -> Self {
LiteralType::String(t.to_string()).into()
}
}
impl From<String> for DataType {
fn from(t: String) -> Self {
LiteralType::String(t).into()
}
}
impl<'a> From<Cow<'a, str>> for DataType {
fn from(t: Cow<'a, str>) -> Self {
LiteralType::String(t.to_string()).into()
}
}