#[derive(Debug)]
pub struct Spec(pub Vec<SpecItem>);
impl Spec {
pub fn iter(&self) -> impl Iterator<Item = &SpecItem> {
self.0.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut SpecItem> {
self.0.iter_mut()
}
}
#[derive(Debug)]
pub enum SpecItem {
StructDef(StructDef),
EnumDef(EnumDef),
ServiceDef(ServiceDef),
}
impl SpecItem {
pub fn service_def(&self) -> Option<&ServiceDef> {
match self {
SpecItem::ServiceDef(s) => Some(s),
_ => None,
}
}
}
#[derive(Debug)]
pub struct StructDef {
pub name: String,
pub fields: StructFields,
pub doc_comment: Option<String>,
}
#[derive(Debug)]
pub struct StructFields(pub Vec<FieldNode>);
impl StructFields {
pub fn iter(&self) -> impl Iterator<Item = &FieldNode> {
self.0.iter()
}
}
#[derive(Debug)]
pub struct EnumDef {
pub name: String,
pub variants: Vec<VariantDef>,
pub doc_comment: Option<String>,
}
impl EnumDef {
pub fn complex_variants(&self) -> impl Iterator<Item = &VariantDef> {
self.variants.iter().filter(|v| !v.is_simple())
}
pub fn simple_variants(&self) -> impl Iterator<Item = &VariantDef> {
self.variants.iter().filter(|v| v.is_simple())
}
}
#[derive(Debug)]
pub struct VariantDef {
pub name: String,
pub variant_type: VariantType,
pub doc_comment: Option<String>,
}
#[derive(Debug)]
pub enum VariantType {
Simple,
Tuple(TupleDef),
Struct(StructFields),
Newtype(TypeIdent),
}
impl VariantType {
pub fn struct_fields(&self) -> Option<&StructFields> {
match self {
VariantType::Struct(f) => Some(f),
_ => None,
}
}
pub fn struct_fields_mut(&mut self) -> Option<&mut StructFields> {
match self {
VariantType::Struct(f) => Some(f),
_ => None,
}
}
}
impl VariantDef {
fn is_simple(&self) -> bool {
if let VariantType::Simple = self.variant_type {
true
} else {
false
}
}
}
#[derive(Debug)]
pub struct ServiceDef {
pub name: String,
pub doc_comment: Option<String>,
pub endpoints: Vec<ServiceEndpoint>,
}
#[derive(Debug)]
pub struct ServiceEndpoint {
pub doc_comment: Option<String>,
pub route: ServiceRoute,
}
#[derive(Debug)]
pub enum ServiceRoute {
Get {
components: Vec<ServiceRouteComponent>,
query: Option<TypeIdent>,
ret: TypeIdent,
},
Post {
components: Vec<ServiceRouteComponent>,
query: Option<TypeIdent>,
body: TypeIdent,
ret: TypeIdent,
},
Delete {
components: Vec<ServiceRouteComponent>,
query: Option<TypeIdent>,
ret: TypeIdent,
},
Put {
components: Vec<ServiceRouteComponent>,
query: Option<TypeIdent>,
body: TypeIdent,
ret: TypeIdent,
},
Patch {
components: Vec<ServiceRouteComponent>,
query: Option<TypeIdent>,
body: TypeIdent,
ret: TypeIdent,
},
}
impl ServiceRoute {
pub fn components(&self) -> &Vec<ServiceRouteComponent> {
match self {
ServiceRoute::Get { components, .. } => components,
ServiceRoute::Delete { components, .. } => components,
ServiceRoute::Post { components, .. } => components,
ServiceRoute::Put { components, .. } => components,
ServiceRoute::Patch { components, .. } => components,
}
}
pub fn query(&self) -> &Option<TypeIdent> {
match self {
ServiceRoute::Get { query, .. } => query,
ServiceRoute::Delete { query, .. } => query,
ServiceRoute::Post { query, .. } => query,
ServiceRoute::Put { query, .. } => query,
ServiceRoute::Patch { query, .. } => query,
}
}
pub fn return_type(&self) -> &TypeIdent {
match self {
ServiceRoute::Get { ret, .. } => ret,
ServiceRoute::Delete { ret, .. } => ret,
ServiceRoute::Post { ret, .. } => ret,
ServiceRoute::Put { ret, .. } => ret,
ServiceRoute::Patch { ret, .. } => ret,
}
}
pub fn request_body(&self) -> Option<&TypeIdent> {
match self {
ServiceRoute::Get { .. } => None,
ServiceRoute::Delete { .. } => None,
ServiceRoute::Post { body, .. } => Some(body),
ServiceRoute::Put { body, .. } => Some(body),
ServiceRoute::Patch { body, .. } => Some(body),
}
}
pub fn http_method_as_str(&self) -> &'static str {
match self {
ServiceRoute::Get { .. } => "GET",
ServiceRoute::Delete { .. } => "DELETE",
ServiceRoute::Post { .. } => "POST",
ServiceRoute::Put { .. } => "PUT",
ServiceRoute::Patch { .. } => "PATCH",
}
}
}
#[derive(Debug, Clone)]
pub enum ServiceRouteComponent {
Literal(String),
Variable(FieldDefPair),
}
#[derive(Debug, Clone)]
pub struct FieldNode {
pub pair: FieldDefPair,
pub doc_comment: Option<String>,
}
#[derive(Debug, Clone)]
pub struct FieldDefPair {
pub name: String,
pub type_ident: TypeIdent,
}
impl FieldDefPair {
pub fn is_embed(&self) -> bool {
self.type_ident
.user_defined()
.map(|ident_name| &self.name == ident_name)
.unwrap_or(false)
}
}
#[derive(Debug, Clone)]
pub enum TypeIdent {
BuiltIn(AtomType),
List(Box<TypeIdent>),
Option(Box<TypeIdent>),
Result(Box<TypeIdent>, Box<TypeIdent>),
Map(Box<TypeIdent>, Box<TypeIdent>),
Tuple(TupleDef),
UserDefined(String),
}
impl TypeIdent {
pub fn user_defined(&self) -> Option<&String> {
match self {
TypeIdent::UserDefined(s) => Some(s),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum AtomType {
Empty,
Str,
I32,
U32,
U8,
F64,
Bool,
DateTime,
Date,
Uuid,
Bytes,
}
#[derive(Debug, Clone)]
pub struct TupleDef(pub Vec<TypeIdent>);
impl TupleDef {
pub fn elements(&self) -> &Vec<TypeIdent> {
&self.0
}
}