use std::collections::BTreeMap;
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Null,
Bool(bool),
String(String),
List(Vec<Value>),
Dict(BTreeMap<String, Value>),
}
impl Value {
pub fn is_null(&self) -> bool {
matches!(self, Value::Null)
}
pub fn is_bool(&self) -> bool {
matches!(self, Value::Bool(_))
}
pub fn is_string(&self) -> bool {
matches!(self, Value::String(_))
}
pub fn is_list(&self) -> bool {
matches!(self, Value::List(_))
}
pub fn is_dict(&self) -> bool {
matches!(self, Value::Dict(_))
}
pub fn as_bool(&self) -> Option<bool> {
if let &Value::Bool(b) = self {
Some(b)
} else {
None
}
}
pub fn as_str(&self) -> Option<&str> {
if let Value::String(s) = self {
Some(s)
} else {
None
}
}
pub fn as_list(&self) -> Option<&[Value]> {
if let Value::List(l) = self {
Some(l)
} else {
None
}
}
pub fn as_dict(&self) -> Option<&BTreeMap<String, Value>> {
if let Value::Dict(m) = self {
Some(m)
} else {
None
}
}
pub fn into_string(self) -> Option<String> {
if let Value::String(s) = self {
Some(s)
} else {
None
}
}
pub fn into_list(self) -> Option<Vec<Value>> {
if let Value::List(l) = self {
Some(l)
} else {
None
}
}
pub fn is_truthy(&self) -> bool {
match self {
Value::Null => false,
Value::Bool(b) => *b,
Value::String(s) => !s.is_empty(),
Value::List(l) => !l.is_empty(),
Value::Dict(m) => !m.is_empty(),
}
}
}
pub trait ToValue {
fn to_value(&self) -> Value;
}
impl ToValue for Value {
fn to_value(&self) -> Value {
self.clone()
}
}
impl<T: ToValue> ToValue for &T {
fn to_value(&self) -> Value {
<T as ToValue>::to_value(self)
}
}
impl<T: ToValue> ToValue for &[T] {
fn to_value(&self) -> Value {
Value::List(self.iter().map(|e| e.to_value()).collect())
}
}
impl ToValue for &str {
fn to_value(&self) -> Value {
Value::String((*self).to_owned())
}
}
impl ToValue for String {
fn to_value(&self) -> Value {
Value::String(self.clone())
}
}
macro_rules! impl_to_value_via_to_string {
($name:ident) => {
impl ToValue for $name {
fn to_value(&self) -> Value {
Value::String(<$name as ::std::string::ToString>::to_string(self))
}
}
};
($($name:ident,)*) => {
$(impl_to_value_via_to_string! { $name })*
}
}
impl_to_value_via_to_string! {
u8, u16, u32, u64, u128,
i8, i16, i32, i64, i128,
bool,
}