extern crate reproto_core as core;
use core::errors::Result;
use core::{Loc, RpNumber, RpPackage, WithSpan};
use std::borrow::Cow;
use std::ops;
use std::result;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ErrorRecovery<T> {
Error,
Value(T),
}
impl<T> ErrorRecovery<T> {
pub fn recover(self) -> Result<T> {
use self::ErrorRecovery::*;
match self {
Error => Err("value not available".into()),
Value(value) => Ok(value),
}
}
}
impl<T> From<T> for ErrorRecovery<T> {
fn from(value: T) -> ErrorRecovery<T> {
ErrorRecovery::Value(value)
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct Item<'input, T> {
pub comment: Vec<Cow<'input, str>>,
pub attributes: Vec<Loc<Attribute<'input>>>,
pub item: Loc<T>,
}
impl<'input, T> ops::Deref for Item<'input, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
Loc::value(&self.item)
}
}
impl<'input, T> Item<'input, T> {
pub fn map<F, E: WithSpan, U>(self, f: F) -> result::Result<Loc<U>, E>
where
F: FnOnce(Vec<Cow<'input, str>>, Vec<Loc<Attribute<'input>>>, Loc<T>)
-> result::Result<U, E>,
{
let span = Loc::span(&self.item).clone();
match f(self.comment, self.attributes, self.item) {
Ok(o) => Ok(Loc::new(o, span)),
Err(e) => Err(e.with_span(span)),
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum AttributeItem<'input> {
Word(Loc<Value<'input>>),
NameValue {
name: Loc<Cow<'input, str>>,
value: Loc<Value<'input>>,
},
}
#[derive(Debug, PartialEq, Eq)]
pub enum Attribute<'input> {
Word(Loc<Cow<'input, str>>),
List(Loc<Cow<'input, str>>, Vec<AttributeItem<'input>>),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Type {
Double,
Float,
Signed {
size: usize,
},
Unsigned {
size: usize,
},
Boolean,
String,
Bytes,
Any,
DateTime,
Name {
name: Name,
},
Array {
inner: Box<Type>,
},
Map {
key: Box<Type>,
value: Box<Type>,
},
}
#[derive(Debug, PartialEq, Eq)]
pub enum Decl<'input> {
Type(Item<'input, TypeBody<'input>>),
Tuple(Item<'input, TupleBody<'input>>),
Interface(Item<'input, InterfaceBody<'input>>),
Enum(Item<'input, EnumBody<'input>>),
Service(Item<'input, ServiceBody<'input>>),
}
impl<'input> Decl<'input> {
pub fn name(&self) -> &str {
use self::Decl::*;
match *self {
Type(ref body) => &body.name,
Tuple(ref body) => &body.name,
Interface(ref body) => &body.name,
Enum(ref body) => &body.name,
Service(ref body) => &body.name,
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct EnumBody<'input> {
pub name: Cow<'input, str>,
pub ty: Loc<Type>,
pub variants: Vec<Item<'input, EnumVariant<'input>>>,
pub members: Vec<EnumMember<'input>>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct EnumVariant<'input> {
pub name: Loc<Cow<'input, str>>,
pub argument: Option<Loc<Value<'input>>>,
}
#[derive(Debug, PartialEq, Eq)]
pub enum EnumMember<'input> {
Code(Loc<Code<'input>>),
}
#[derive(Debug, PartialEq, Eq)]
pub struct Field<'input> {
pub required: bool,
pub name: Cow<'input, str>,
pub ty: Loc<ErrorRecovery<Type>>,
pub field_as: Option<String>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct File<'input> {
pub comment: Vec<Cow<'input, str>>,
pub attributes: Vec<Loc<Attribute<'input>>>,
pub uses: Vec<Loc<UseDecl<'input>>>,
pub decls: Vec<Decl<'input>>,
}
impl<'input> Field<'input> {
pub fn is_optional(&self) -> bool {
!self.required
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Name {
Relative {
parts: Vec<String>,
},
Absolute {
prefix: Option<String>,
parts: Loc<ErrorRecovery<Vec<String>>>,
},
}
#[derive(Debug, PartialEq, Eq)]
pub struct InterfaceBody<'input> {
pub name: Cow<'input, str>,
pub members: Vec<TypeMember<'input>>,
pub sub_types: Vec<Item<'input, SubType<'input>>>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct Code<'input> {
pub attributes: Vec<Loc<Attribute<'input>>>,
pub context: Loc<Cow<'input, str>>,
pub content: Vec<Cow<'input, str>>,
}
#[derive(Debug, PartialEq, Eq)]
pub enum TypeMember<'input> {
Field(Item<'input, Field<'input>>),
Code(Loc<Code<'input>>),
InnerDecl(Decl<'input>),
}
#[derive(Debug, PartialEq, Eq)]
pub struct ServiceBody<'input> {
pub name: Cow<'input, str>,
pub members: Vec<ServiceMember<'input>>,
}
#[derive(Debug, PartialEq, Eq)]
pub enum ServiceMember<'input> {
Endpoint(Item<'input, Endpoint<'input>>),
InnerDecl(Decl<'input>),
}
#[derive(Debug, PartialEq, Eq)]
pub struct EndpointArgument<'input> {
pub ident: Loc<Cow<'input, str>>,
pub channel: Loc<Channel>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct Endpoint<'input> {
pub id: Loc<Cow<'input, str>>,
pub alias: Option<String>,
pub arguments: Vec<EndpointArgument<'input>>,
pub response: Option<Loc<Channel>>,
}
#[derive(Debug, PartialEq, Eq)]
pub enum Channel {
Unary { ty: Type },
Streaming { ty: Type },
}
#[derive(Debug, PartialEq, Eq)]
pub struct SubType<'input> {
pub name: Loc<Cow<'input, str>>,
pub members: Vec<TypeMember<'input>>,
pub alias: Option<Loc<Value<'input>>>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct TupleBody<'input> {
pub name: Cow<'input, str>,
pub members: Vec<TypeMember<'input>>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct TypeBody<'input> {
pub name: Cow<'input, str>,
pub members: Vec<TypeMember<'input>>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct UseDecl<'input> {
pub package: Loc<RpPackage>,
pub range: Option<Loc<String>>,
pub alias: Option<Loc<Cow<'input, str>>>,
}
#[derive(Debug, PartialEq, Eq)]
pub enum Value<'input> {
String(String),
Number(RpNumber),
Identifier(Cow<'input, str>),
Array(Vec<Loc<Value<'input>>>),
}
#[derive(Debug, PartialEq, Eq)]
pub enum PathPart<'input> {
Variable(Cow<'input, str>),
Segment(String),
}
#[derive(Debug, PartialEq, Eq)]
pub struct PathStep<'input> {
pub parts: Vec<PathPart<'input>>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct PathSpec<'input> {
pub steps: Vec<PathStep<'input>>,
}