use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Span {
pub start: usize,
pub end: usize,
pub line: u32,
pub column: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Version {
V1,
V2,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Ruleset {
pub version: Version,
pub file_name: Option<String>,
pub functions: Vec<Function>,
pub services: Vec<Service>,
pub parens: HashMap<(usize, usize), Vec<Span>>,
}
impl Ruleset {
pub fn service(&self, name: &str) -> Option<&Service> {
self.services.iter().find(|s| s.name == name)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Service {
pub name: String,
pub name_span: Span,
pub body: Body,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Body {
pub functions: Vec<Function>,
pub matches: Vec<Match>,
pub allows: Vec<Allow>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Match {
pub path: Vec<Segment>,
pub body: Body,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Segment {
pub kind: SegmentKind,
pub span: Span,
pub name_span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SegmentKind {
Literal(String),
Wildcard(String),
Recursive(String),
}
impl SegmentKind {
pub fn variable(&self) -> Option<&str> {
match self {
Self::Literal(_) => None,
Self::Wildcard(name) | Self::Recursive(name) => Some(name),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Allow {
pub methods: Vec<MethodName>,
pub condition: Option<Expr>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MethodName {
pub name: String,
pub method: Option<Method>,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Method {
Read,
Write,
Get,
List,
Create,
Update,
Delete,
}
impl Method {
pub fn from_name(name: &str) -> Option<Self> {
Some(match name {
"read" => Self::Read,
"write" => Self::Write,
"get" => Self::Get,
"list" => Self::List,
"create" => Self::Create,
"update" => Self::Update,
"delete" => Self::Delete,
_ => return None,
})
}
pub fn covers(self, request: Self) -> bool {
self == request
|| matches!(
(self, request),
(Self::Read, Self::Get | Self::List)
| (Self::Write, Self::Create | Self::Update | Self::Delete)
)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Function {
pub name: Ident,
pub params: Vec<Ident>,
pub lets: Vec<Let>,
pub result: Expr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Let {
pub name: Ident,
pub value: Expr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Ident {
pub name: String,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Expr {
pub kind: ExprKind,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ExprKind {
Null,
Bool(bool),
Int(i64),
IntOverflow(String),
Float(f64),
String(String),
Bytes(Vec<u8>),
Ident(String),
List(Vec<Expr>),
Map(Vec<(Expr, Expr)>),
Path(Vec<PathPart>),
Member {
object: Box<Expr>,
field: Ident,
},
Index {
object: Box<Expr>,
index: Box<Expr>,
},
Slice {
object: Box<Expr>,
start: Box<Expr>,
end: Box<Expr>,
},
Call {
callee: Callee,
args: Vec<Expr>,
},
Unary {
op: UnaryOp,
operand: Box<Expr>,
},
Binary {
op: BinaryOp,
op_span: Span,
left: Box<Expr>,
right: Box<Expr>,
},
Is {
value: Box<Expr>,
keyword: Span,
type_name: Ident,
},
Ternary {
condition: Box<Expr>,
question: Span,
then: Box<Expr>,
otherwise: Box<Expr>,
},
}
#[derive(Debug, Clone, PartialEq)]
pub enum Callee {
Global(Ident),
Namespaced { namespace: Ident, name: Ident },
Method { receiver: Box<Expr>, name: Ident },
}
#[derive(Debug, Clone, PartialEq)]
pub enum PathPart {
Segment(String),
Expr(Expr),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
Not,
Neg,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOp {
Or,
And,
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
In,
Add,
Sub,
Mul,
Div,
Mod,
}