pub mod types;
pub use types::{
CustomAnnotation, CustomAnnotationArg, CustomAnnotationValue, DeprecatedInfo, Encoding,
FieldEncoding, ResolvedAnnotations, ResolvedType, TombstoneDef, TypeId, TypeRegistry, WireSize,
POISON_TYPE_ID,
};
use crate::ast::{DefaultValue, EnumBacking};
use crate::span::Span;
use smol_str::SmolStr;
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq)]
pub enum FieldConstraint {
And(Box<FieldConstraint>, Box<FieldConstraint>),
Or(Box<FieldConstraint>, Box<FieldConstraint>),
Not(Box<FieldConstraint>),
Cmp {
op: CmpOp,
operand: ConstraintOperand,
},
Range {
low: ConstraintOperand,
high: ConstraintOperand,
exclusive_high: bool,
},
LenCmp {
op: CmpOp,
operand: ConstraintOperand,
},
LenRange {
low: ConstraintOperand,
high: ConstraintOperand,
exclusive_high: bool,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CmpOp {
Eq,
Ne,
Lt,
Gt,
Le,
Ge,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ConstraintOperand {
Int(i64),
Float(f64),
String(String),
Bool(bool),
ConstRef(SmolStr),
}
#[derive(Debug, Clone)]
pub struct CompiledSchema {
pub namespace: Vec<SmolStr>,
pub annotations: ResolvedAnnotations,
pub registry: TypeRegistry,
pub declarations: Vec<TypeId>,
pub constants: HashMap<SmolStr, ConstValue>,
}
const _: fn() = || {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<CompiledSchema>();
};
impl CompiledSchema {
pub fn impls(&self) -> impl Iterator<Item = (TypeId, &ImplDef)> {
self.registry.iter().filter_map(|(id, def)| match def {
TypeDef::Impl(impl_def) => Some((id, impl_def)),
_ => None,
})
}
pub fn type_names(&self) -> Vec<&str> {
self.declarations
.iter()
.filter_map(|&id| self.registry.get(id))
.map(|def| match def {
TypeDef::Message(m) => m.name.as_str(),
TypeDef::Enum(e) => e.name.as_str(),
TypeDef::Flags(f) => f.name.as_str(),
TypeDef::Union(u) => u.name.as_str(),
TypeDef::Newtype(n) => n.name.as_str(),
TypeDef::Config(c) => c.name.as_str(),
TypeDef::GenericAlias(g) => g.name.as_str(),
TypeDef::Trait(t) => t.name.as_str(),
TypeDef::Impl(_) => "", })
.filter(|s| !s.is_empty())
.collect()
}
pub fn find_type(&self, name: &str) -> Option<(TypeId, &TypeDef)> {
for &id in &self.declarations {
if let Some(def) = self.registry.get(id) {
let def_name = match def {
TypeDef::Message(m) => m.name.as_str(),
TypeDef::Enum(e) => e.name.as_str(),
TypeDef::Flags(f) => f.name.as_str(),
TypeDef::Union(u) => u.name.as_str(),
TypeDef::Newtype(n) => n.name.as_str(),
TypeDef::Config(c) => c.name.as_str(),
TypeDef::GenericAlias(g) => g.name.as_str(),
TypeDef::Trait(t) => t.name.as_str(),
TypeDef::Impl(_) => continue, };
if def_name == name {
return Some((id, def));
}
}
}
None
}
pub fn namespace_str(&self) -> String {
self.namespace
.iter()
.map(|s| s.as_str())
.collect::<Vec<_>>()
.join(".")
}
pub fn hash_hex(&self) -> String {
let hash = crate::canonical::schema_hash(self);
hash.iter().map(|b| format!("{b:02x}")).collect()
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ConstValue {
pub ty: ResolvedType,
pub value: i64,
pub span: Span,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum TypeDef {
Message(MessageDef),
Enum(EnumDef),
Flags(FlagsDef),
Union(UnionDef),
Newtype(NewtypeDef),
Config(ConfigDef),
GenericAlias(GenericAliasDef),
Trait(TraitDef),
Impl(ImplDef),
}
#[derive(Debug, Clone)]
pub struct MessageDef {
pub name: SmolStr,
pub span: Span,
pub fields: Vec<FieldDef>,
pub tombstones: Vec<TombstoneDef>,
pub annotations: ResolvedAnnotations,
pub wire_size: Option<WireSize>,
}
#[derive(Debug, Clone)]
pub struct FieldDef {
pub name: SmolStr,
pub span: Span,
pub ordinal: u32,
pub resolved_type: ResolvedType,
pub encoding: FieldEncoding,
pub annotations: ResolvedAnnotations,
pub constraint: Option<FieldConstraint>,
}
#[derive(Debug, Clone)]
pub struct EnumDef {
pub name: SmolStr,
pub span: Span,
pub backing: Option<EnumBacking>,
pub variants: Vec<EnumVariantDef>,
pub tombstones: Vec<TombstoneDef>,
pub annotations: ResolvedAnnotations,
pub wire_bits: u8,
}
#[derive(Debug, Clone)]
pub struct EnumVariantDef {
pub name: SmolStr,
pub span: Span,
pub ordinal: u32,
pub annotations: ResolvedAnnotations,
}
#[derive(Debug, Clone)]
pub struct FlagsDef {
pub name: SmolStr,
pub span: Span,
pub bits: Vec<FlagsBitDef>,
pub tombstones: Vec<TombstoneDef>,
pub annotations: ResolvedAnnotations,
pub wire_bytes: u8,
}
#[derive(Debug, Clone)]
pub struct FlagsBitDef {
pub name: SmolStr,
pub span: Span,
pub bit: u32,
pub annotations: ResolvedAnnotations,
}
#[derive(Debug, Clone)]
pub struct UnionDef {
pub name: SmolStr,
pub span: Span,
pub variants: Vec<UnionVariantDef>,
pub tombstones: Vec<TombstoneDef>,
pub annotations: ResolvedAnnotations,
pub wire_size: Option<WireSize>,
}
#[derive(Debug, Clone)]
pub struct UnionVariantDef {
pub name: SmolStr,
pub span: Span,
pub ordinal: u32,
pub fields: Vec<FieldDef>,
pub tombstones: Vec<TombstoneDef>,
pub annotations: ResolvedAnnotations,
}
#[derive(Debug, Clone)]
pub struct NewtypeDef {
pub name: SmolStr,
pub span: Span,
pub inner_type: ResolvedType,
pub terminal_type: ResolvedType,
pub annotations: ResolvedAnnotations,
}
#[derive(Debug, Clone)]
pub struct ConfigDef {
pub name: SmolStr,
pub span: Span,
pub fields: Vec<ConfigFieldDef>,
pub annotations: ResolvedAnnotations,
}
#[derive(Debug, Clone)]
pub struct ConfigFieldDef {
pub name: SmolStr,
pub span: Span,
pub resolved_type: ResolvedType,
pub default_value: DefaultValue,
pub annotations: ResolvedAnnotations,
}
#[derive(Debug, Clone)]
pub struct GenericAliasDef {
pub name: SmolStr,
pub span: Span,
pub type_params: Vec<SmolStr>,
pub target_type: crate::ast::TypeExpr,
pub annotations: ResolvedAnnotations,
}
#[derive(Debug, Clone)]
pub struct TraitDef {
pub name: SmolStr,
pub type_params: Vec<crate::ast::TypeParam>,
pub fields: Vec<TraitFieldDef>,
pub functions: Vec<TraitFnDef>,
pub annotations: ResolvedAnnotations,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct TraitFieldDef {
pub name: SmolStr,
pub ty: ResolvedType,
pub unresolved_ty: crate::ast::TypeExpr,
pub ordinal: u32,
pub annotations: ResolvedAnnotations,
}
#[derive(Debug, Clone)]
pub struct TraitFnDef {
pub name: SmolStr,
pub params: Vec<FnParamDef>,
pub return_type: Option<ResolvedType>,
}
#[derive(Debug, Clone)]
pub struct FnParamDef {
pub name: SmolStr,
pub ty: ResolvedType,
pub unresolved_ty: crate::ast::TypeExpr,
}
#[derive(Debug, Clone)]
pub struct ImplDef {
pub trait_name: SmolStr,
pub target_type: ResolvedType,
pub type_args: Vec<ResolvedType>, pub functions: Vec<ImplFnDef>,
pub annotations: ResolvedAnnotations,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct ImplFnDef {
pub name: SmolStr,
pub params: Vec<FnParamDef>,
pub return_type: Option<ResolvedType>,
pub body: FnBody,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinOp {
Add,
Sub,
Mul,
Div,
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
Neg,
Not,
}
#[derive(Debug, Clone)]
pub enum Expr {
Int(i64),
UInt(u64),
Float(f64),
Bool(bool),
String(String),
Local(SmolStr),
FieldAccess(Box<Expr>, SmolStr),
Call(SmolStr, Vec<Expr>),
TraitMethodCall {
trait_name: SmolStr,
method_name: SmolStr,
receiver: Box<Expr>,
args: Vec<Expr>,
},
Binary(BinOp, Box<Expr>, Box<Expr>),
Unary(UnaryOp, Box<Expr>),
SelfRef,
}
#[derive(Debug, Clone)]
pub enum Statement {
Expr(Expr),
Let {
name: SmolStr,
ty: Option<ResolvedType>,
value: Expr,
},
Return(Option<Expr>),
Assign {
target: Expr,
value: Expr,
},
}
#[derive(Debug, Clone)]
pub enum FnBody {
External,
Block(Vec<Statement>),
}