use std::collections::BTreeMap;
use std::convert::Infallible;
use std::fmt;
use std::str::FromStr;
use crate::span::Spanned;
pub type SpannedChildren<S> = Spanned<Vec<SpannedNode<S>>, S>;
pub type SpannedName<S> = Spanned<Box<str>, S>;
pub type SpannedNode<S> = Spanned<Node<S>, S>;
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
#[cfg_attr(feature = "minicbor", derive(minicbor::Encode, minicbor::Decode))]
pub struct Node<S> {
#[cfg_attr(feature = "minicbor", n(0))]
pub type_name: Option<Spanned<TypeName, S>>,
#[cfg_attr(feature = "minicbor", n(1))]
pub node_name: SpannedName<S>,
#[cfg_attr(feature = "minicbor", n(2))]
pub arguments: Vec<Value<S>>,
#[cfg_attr(feature = "minicbor", n(3))]
pub properties: BTreeMap<SpannedName<S>, Value<S>>,
#[cfg_attr(feature = "minicbor", n(4))]
pub children: Option<SpannedChildren<S>>,
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
#[cfg_attr(feature = "minicbor", derive(minicbor::Encode, minicbor::Decode))]
pub struct Document<S> {
#[cfg_attr(feature = "minicbor", n(0))]
pub nodes: Vec<SpannedNode<S>>,
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
#[cfg_attr(feature = "minicbor", derive(minicbor::Encode, minicbor::Decode))]
#[cfg_attr(feature = "minicbor", cbor(index_only))]
pub enum Radix {
#[cfg_attr(feature = "minicbor", n(2))]
Bin,
#[cfg_attr(feature = "minicbor", n(8))]
Oct,
#[default]
#[cfg_attr(feature = "minicbor", n(10))]
Dec,
#[cfg_attr(feature = "minicbor", n(16))]
Hex,
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
#[cfg_attr(feature = "minicbor", derive(minicbor::Encode, minicbor::Decode))]
pub struct Integer(
#[cfg_attr(feature = "minicbor", n(0))] pub Radix,
#[cfg_attr(feature = "minicbor", n(1))] pub Box<str>,
);
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
#[cfg_attr(feature = "minicbor", derive(minicbor::Encode, minicbor::Decode))]
#[cfg_attr(feature = "minicbor", cbor(transparent))]
pub struct Decimal(#[cfg_attr(feature = "minicbor", n(0))] pub Box<str>);
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
#[cfg_attr(feature = "minicbor", derive(minicbor::Encode, minicbor::Decode))]
pub struct Value<S> {
#[cfg_attr(feature = "minicbor", n(0))]
pub type_name: Option<Spanned<TypeName, S>>,
#[cfg_attr(feature = "minicbor", n(1))]
pub literal: Spanned<Literal, S>,
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct TypeName(TypeNameInner);
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
enum TypeNameInner {
Builtin(BuiltinType),
Custom(Box<str>),
}
#[non_exhaustive]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum BuiltinType {
U8,
I8,
U16,
I16,
U32,
I32,
U64,
I64,
U128,
I128,
Usize,
Isize,
F32,
F64,
Base64,
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
#[cfg_attr(feature = "minicbor", derive(minicbor::Encode, minicbor::Decode))]
pub enum Literal {
#[default]
#[cfg_attr(feature = "minicbor", n(0))]
Null,
#[cfg_attr(feature = "minicbor", n(1))]
Bool(#[cfg_attr(feature = "minicbor", n(0))] bool),
#[cfg_attr(feature = "minicbor", n(2))]
Int(#[cfg_attr(feature = "minicbor", n(0))] Integer),
#[cfg_attr(feature = "minicbor", n(3))]
Decimal(#[cfg_attr(feature = "minicbor", n(0))] Decimal),
#[cfg_attr(feature = "minicbor", n(4))]
String(#[cfg_attr(feature = "minicbor", n(0))] Box<str>),
#[cfg_attr(feature = "minicbor", n(5))]
Nan,
#[cfg_attr(feature = "minicbor", n(6))]
Inf,
#[cfg_attr(feature = "minicbor", n(7))]
NegInf,
}
impl<S> Node<S> {
pub fn children(&self) -> impl ExactSizeIterator<Item = &Spanned<Node<S>, S>> {
self.children
.as_ref()
.map(|c| c.iter())
.unwrap_or_else(|| [].iter())
}
}
impl BuiltinType {
pub const fn as_str(&self) -> &'static str {
use BuiltinType::*;
match self {
U8 => "u8",
I8 => "i8",
U16 => "u16",
I16 => "i16",
U32 => "u32",
I32 => "i32",
U64 => "u64",
I64 => "i64",
U128 => "u128",
I128 => "i128",
Usize => "usize",
Isize => "isize",
F32 => "f32",
F64 => "f64",
Base64 => "base64",
}
}
pub const fn as_type(self) -> TypeName {
TypeName(TypeNameInner::Builtin(self))
}
}
impl TypeName {
pub(crate) fn from_string(val: Box<str>) -> TypeName {
use TypeNameInner::*;
match BuiltinType::from_str(&val[..]) {
Ok(b) => TypeName(Builtin(b)),
_ => TypeName(Custom(val)),
}
}
pub fn as_str(&self) -> &str {
match &self.0 {
TypeNameInner::Builtin(t) => t.as_str(),
TypeNameInner::Custom(t) => t.as_ref(),
}
}
pub const fn as_builtin(&self) -> Option<&BuiltinType> {
match &self.0 {
TypeNameInner::Builtin(t) => Some(t),
TypeNameInner::Custom(_) => None,
}
}
}
impl FromStr for BuiltinType {
type Err = ();
fn from_str(s: &str) -> Result<BuiltinType, ()> {
use BuiltinType::*;
match s {
"u8" => Ok(U8),
"i8" => Ok(I8),
"u16" => Ok(U16),
"i16" => Ok(I16),
"u32" => Ok(U32),
"i32" => Ok(I32),
"u64" => Ok(U64),
"i64" => Ok(I64),
"u128" => Ok(U128),
"i128" => Ok(I128),
"f32" => Ok(F32),
"f64" => Ok(F64),
"base64" => Ok(Base64),
_ => Err(()),
}
}
}
impl FromStr for TypeName {
type Err = Infallible;
fn from_str(s: &str) -> Result<TypeName, Infallible> {
use TypeNameInner::*;
match BuiltinType::from_str(s) {
Ok(b) => Ok(TypeName(Builtin(b))),
Err(()) => Ok(TypeName(Custom(s.into()))),
}
}
}
impl std::ops::Deref for TypeName {
type Target = str;
fn deref(&self) -> &str {
self.as_str()
}
}
impl fmt::Display for TypeName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.as_str().fmt(f)
}
}
impl From<BuiltinType> for TypeName {
fn from(val: BuiltinType) -> Self {
val.as_type()
}
}
#[cfg(feature = "minicbor")]
mod cbor {
use super::TypeName;
use minicbor::decode::Decode;
use minicbor::encode::Encode;
use minicbor::{Decoder, Encoder};
impl<'d, C> Decode<'d, C> for TypeName {
fn decode(d: &mut Decoder<'d>, _ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
d.str().and_then(|s| s.parse().map_err(|e| match e {}))
}
}
impl<C> Encode<C> for TypeName {
fn encode<W>(
&self,
e: &mut Encoder<W>,
ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>>
where
W: minicbor::encode::write::Write,
{
self.as_str().encode(e, ctx)
}
}
}