use std::fmt;
#[derive(Debug, Clone)]
pub enum Literal {
Int(i64),
Float(f64),
String(String),
Bool(bool),
Null,
}
impl fmt::Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Literal::Int(n) => write!(f, "{n}"),
Literal::Float(n) => write!(f, "{n:?}"),
Literal::String(s) => write!(f, "'{s}'"),
Literal::Bool(b) => write!(f, "{b}"),
Literal::Null => write!(f, "null"),
}
}
}
pub trait FromLiteral {
fn from_literal(literal: Literal) -> Option<Self>
where
Self: Sized;
}
pub trait VariantValue: FromLiteral {
type VariantArray: ConcreteVariantArray<Value = Self>;
type VariantObject: ConcreteVariantObject<Value = Self>;
fn is_null(&self) -> bool;
fn is_boolean(&self) -> bool;
fn is_string(&self) -> bool;
fn is_array(&self) -> bool;
fn is_object(&self) -> bool;
fn as_bool(&self) -> Option<bool>;
fn as_str(&self) -> Option<&str>;
fn as_array(&self) -> Option<&Self::VariantArray>;
fn as_object(&self) -> Option<&Self::VariantObject>;
fn is_less_than(&self, other: &Self) -> bool;
fn is_equal_to(&self, other: &Self) -> bool;
}
pub trait ConcreteVariantArray {
type Value: VariantValue<VariantArray = Self>;
fn is_empty(&self) -> bool;
fn len(&self) -> usize;
fn get(&self, index: usize) -> Option<&Self::Value>;
fn iter(&self) -> impl Iterator<Item = &Self::Value>;
}
pub trait ConcreteVariantObject {
type Value: VariantValue<VariantObject = Self>;
fn is_empty(&self) -> bool;
fn len(&self) -> usize;
fn get(&self, key: &str) -> Option<&Self::Value>;
fn get_key_value(&self, key: &str) -> Option<(&String, &Self::Value)>;
fn iter(&self) -> impl Iterator<Item = (&String, &Self::Value)>;
fn values(&self) -> impl Iterator<Item = &Self::Value>;
}