use super::{Ident, LitPosInt, LitUuid, TypeNameOrInline};
use crate::error::{
DuplicateEventId, DuplicateFunctionId, DuplicateServiceItem, InvalidServiceUuid,
InvalidServiceVersion,
};
use crate::grammar::Rule;
use crate::validate::Validate;
use crate::warning::{NonCamelCaseService, NonSnakeCaseEvent, NonSnakeCaseFunction};
use crate::Span;
use pest::iterators::Pair;
#[derive(Debug, Clone)]
pub struct ServiceDef {
span: Span,
name: Ident,
uuid: LitUuid,
ver: LitPosInt,
items: Vec<ServiceItem>,
}
impl ServiceDef {
pub(crate) fn parse(pair: Pair<Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::service_def);
let span = Span::from_pair(&pair);
let mut pairs = pair.into_inner();
pairs.next().unwrap(); let pair = pairs.next().unwrap();
let name = Ident::parse(pair);
pairs.next().unwrap(); let pair = pairs.next().unwrap();
let uuid = Self::parse_uuid(pair);
let pair = pairs.next().unwrap();
let ver = Self::parse_version(pair);
let mut items = Vec::new();
for pair in pairs {
match pair.as_rule() {
Rule::service_item => items.push(ServiceItem::parse(pair)),
Rule::tok_cur_close => break,
_ => unreachable!(),
}
}
ServiceDef {
span,
name,
uuid,
ver,
items,
}
}
fn parse_uuid(pair: Pair<Rule>) -> LitUuid {
assert_eq!(pair.as_rule(), Rule::service_uuid);
let mut pairs = pair.into_inner();
pairs.next().unwrap(); pairs.next().unwrap(); let pair = pairs.next().unwrap();
LitUuid::parse(pair)
}
fn parse_version(pair: Pair<Rule>) -> LitPosInt {
assert_eq!(pair.as_rule(), Rule::service_version);
let mut pairs = pair.into_inner();
pairs.next().unwrap(); pairs.next().unwrap(); let pair = pairs.next().unwrap();
LitPosInt::parse(pair)
}
pub(crate) fn validate(&self, validate: &mut Validate) {
InvalidServiceUuid::validate(self, validate);
InvalidServiceVersion::validate(self, validate);
DuplicateServiceItem::validate(self, validate);
DuplicateFunctionId::validate(self, validate);
DuplicateEventId::validate(self, validate);
NonCamelCaseService::validate(self, validate);
self.name.validate(validate);
for item in &self.items {
item.validate(validate);
}
}
pub fn span(&self) -> Span {
self.span
}
pub fn name(&self) -> &Ident {
&self.name
}
pub fn uuid(&self) -> &LitUuid {
&self.uuid
}
pub fn version(&self) -> &LitPosInt {
&self.ver
}
pub fn items(&self) -> &[ServiceItem] {
&self.items
}
}
#[derive(Debug, Clone)]
pub enum ServiceItem {
Function(FunctionDef),
Event(EventDef),
}
impl ServiceItem {
fn parse(pair: Pair<Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::service_item);
let mut pairs = pair.into_inner();
let pair = pairs.next().unwrap();
match pair.as_rule() {
Rule::fn_def => ServiceItem::Function(FunctionDef::parse(pair)),
Rule::event_def => ServiceItem::Event(EventDef::parse(pair)),
_ => unreachable!(),
}
}
fn validate(&self, validate: &mut Validate) {
match self {
ServiceItem::Function(i) => i.validate(validate),
ServiceItem::Event(i) => i.validate(validate),
}
}
pub fn span(&self) -> Span {
match self {
ServiceItem::Function(i) => i.span(),
ServiceItem::Event(i) => i.span(),
}
}
pub fn name(&self) -> &Ident {
match self {
ServiceItem::Function(i) => i.name(),
ServiceItem::Event(i) => i.name(),
}
}
}
#[derive(Debug, Clone)]
pub struct FunctionDef {
span: Span,
name: Ident,
id: LitPosInt,
args: Option<FunctionPart>,
ok: Option<FunctionPart>,
err: Option<FunctionPart>,
}
impl FunctionDef {
fn parse(pair: Pair<Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::fn_def);
let span = Span::from_pair(&pair);
let mut pairs = pair.into_inner();
pairs.next().unwrap(); let pair = pairs.next().unwrap();
let name = Ident::parse(pair);
pairs.next().unwrap(); let pair = pairs.next().unwrap();
let id = LitPosInt::parse(pair);
let mut args = None;
let mut ok = None;
let mut err = None;
for pair in pairs {
match pair.as_rule() {
Rule::tok_cur_open => {}
Rule::fn_args => args = Some(FunctionPart::parse(pair)),
Rule::fn_ok => ok = Some(FunctionPart::parse(pair)),
Rule::fn_err => err = Some(FunctionPart::parse(pair)),
Rule::tok_cur_close | Rule::tok_term => break,
_ => unreachable!(),
}
}
FunctionDef {
span,
name,
id,
args,
ok,
err,
}
}
fn validate(&self, validate: &mut Validate) {
NonSnakeCaseFunction::validate(self, validate);
self.name.validate(validate);
if let Some(ref args) = self.args {
args.validate(validate);
}
if let Some(ref ok) = self.ok {
ok.validate(validate);
}
if let Some(ref err) = self.err {
err.validate(validate);
}
}
pub fn span(&self) -> Span {
self.span
}
pub fn name(&self) -> &Ident {
&self.name
}
pub fn id(&self) -> &LitPosInt {
&self.id
}
pub fn args(&self) -> Option<&FunctionPart> {
self.args.as_ref()
}
pub fn ok(&self) -> Option<&FunctionPart> {
self.ok.as_ref()
}
pub fn err(&self) -> Option<&FunctionPart> {
self.err.as_ref()
}
}
#[derive(Debug, Clone)]
pub struct FunctionPart {
span: Span,
part_type: TypeNameOrInline,
}
impl FunctionPart {
fn parse(pair: Pair<Rule>) -> Self {
assert!(
(pair.as_rule() == Rule::fn_args)
|| (pair.as_rule() == Rule::fn_ok)
|| (pair.as_rule() == Rule::fn_err)
);
let span = Span::from_pair(&pair);
let mut pairs = pair.into_inner();
pairs.next().unwrap(); pairs.next().unwrap(); let pair = pairs.next().unwrap();
let part_type = TypeNameOrInline::parse(pair);
FunctionPart { span, part_type }
}
fn validate(&self, validate: &mut Validate) {
self.part_type.validate(validate);
}
pub fn span(&self) -> Span {
self.span
}
pub fn part_type(&self) -> &TypeNameOrInline {
&self.part_type
}
}
#[derive(Debug, Clone)]
pub struct EventDef {
span: Span,
name: Ident,
id: LitPosInt,
event_type: Option<TypeNameOrInline>,
}
impl EventDef {
fn parse(pair: Pair<Rule>) -> Self {
assert_eq!(pair.as_rule(), Rule::event_def);
let span = Span::from_pair(&pair);
let mut pairs = pair.into_inner();
pairs.next().unwrap(); let pair = pairs.next().unwrap();
let name = Ident::parse(pair);
pairs.next().unwrap(); let pair = pairs.next().unwrap();
let id = LitPosInt::parse(pair);
let pair = pairs.next().unwrap();
let event_type = match pair.as_rule() {
Rule::tok_eq => {
let pair = pairs.next().unwrap();
Some(TypeNameOrInline::parse(pair))
}
Rule::tok_term => None,
_ => unreachable!(),
};
EventDef {
span,
name,
id,
event_type,
}
}
fn validate(&self, validate: &mut Validate) {
NonSnakeCaseEvent::validate(self, validate);
self.name.validate(validate);
if let Some(ref event_type) = self.event_type {
event_type.validate(validate);
}
}
pub fn span(&self) -> Span {
self.span
}
pub fn name(&self) -> &Ident {
&self.name
}
pub fn id(&self) -> &LitPosInt {
&self.id
}
pub fn event_type(&self) -> Option<&TypeNameOrInline> {
self.event_type.as_ref()
}
}