use std::fmt::Debug;
use crate::value::bytes::Bytes;
use crate::value::dictionary::Dictionary;
use std::iter::FromIterator;
pub mod bytes;
pub mod dictionary;
#[derive(Debug, Clone, PartialEq)]
pub enum Value<S> {
Null,
Boolean(bool),
Integer(i64),
Float(f64),
Bytes(Bytes),
String(String),
List(Vec<Value<S>>),
Dictionary(Dictionary<S>),
Structure(S)
}
impl<S> From<i64> for Value<S> {
fn from(i: i64) -> Self {
Value::Integer(i)
}
}
impl<S> From<bool> for Value<S> {
fn from(b: bool) -> Self {
Value::Boolean(b)
}
}
impl<S> From<f64> for Value<S> {
fn from(f: f64) -> Self {
Value::Float(f)
}
}
impl<S> From<&str> for Value<S> {
fn from(s: &str) -> Self {
Value::String(String::from(s))
}
}
impl<S> From<String> for Value<S> {
fn from(s: String) -> Self {
Value::String(s)
}
}
impl<S> From<Vec<Value<S>>> for Value<S> {
fn from(s: Vec<Value<S>>) -> Self {
Value::List(s)
}
}
impl<S, V: Into<Value<S>>> From<Option<V>> for Value<S> {
fn from(opt: Option<V>) -> Self {
if let Some(v) = opt {
v.into()
} else {
Value::Null
}
}
}
impl<S, V: Into<Value<S>>> FromIterator<V> for Value<S> {
fn from_iter<T: IntoIterator<Item=V>>(iter: T) -> Self {
Value::List(iter.into_iter().map(|v| v.into()).collect())
}
}
impl<S, V: Into<Value<S>>> FromIterator<(String, V)> for Value<S> {
fn from_iter<T: IntoIterator<Item=(String, V)>>(iter: T) -> Self {
Value::Dictionary(
iter.into_iter().map(|(key, val)| (key, val.into())).collect()
)
}
}
pub trait Extract<T> : Sized {
fn extract(from: Value<T>) -> Option<Self>;
}
pub trait ExtractRef<T> : Sized {
fn extract_ref(from: &Value<T>) -> Option<&Self>;
fn extract_opt_ref(from: &Value<T>) -> Option<Option<&Self>> {
match from {
Value::Null => Some(None),
v => Self::extract_ref(v).map(Some)
}
}
}
pub trait ExtractMut<T> : Sized {
fn extract_mut(from: &mut Value<T>) -> Option<&mut Self>;
fn extract_opt_mut(from: &mut Value<T>) -> Option<Option<&mut Self>> {
match from {
Value::Null => Some(None),
v => Self::extract_mut(v).map(Some)
}
}
}
macro_rules! impl_extract {
($ty_for:ty, $into:ident) => {
impl<T> Extract<T> for $ty_for {
fn extract(from: Value<T>) -> Option<Self> {
match from {
Value::$into(x) => Some(x),
_ => None,
}
}
}
impl<T> ExtractRef<T> for $ty_for {
fn extract_ref(from: &Value<T>) -> Option<&Self> {
match from {
Value::$into(x) => Some(x),
_ => None,
}
}
}
impl<T> ExtractMut<T> for $ty_for {
fn extract_mut(from: &mut Value<T>) -> Option<&mut Self> {
match from {
Value::$into(x) => Some(x),
_ => None,
}
}
}
}
}
impl_extract!(i64, Integer);
impl_extract!(f64, Float);
impl_extract!(bool, Boolean);
impl_extract!(Bytes, Bytes);
impl_extract!(String, String);
impl_extract!(Vec<Value<T>>, List);
impl_extract!(Dictionary<T>, Dictionary);
impl<T, E: Extract<T>> Extract<T> for Option<E> {
fn extract(from: Value<T>) -> Option<Self> {
match from {
Value::Null => Some(None),
v => E::extract(v).map(Some)
}
}
}
pub fn extract_list_ref<S, T: ExtractRef<S>>(value: &Value<S>) -> Option<Vec<&T>> {
match value {
Value::List(vs) => {
let extracted : Vec<&T> = vs.iter().flat_map(T::extract_ref).collect();
if extracted.len() < vs.len() {
None
} else {
Some(extracted)
}
},
_ => None,
}
}
pub fn extract_list<S, T: Extract<S>>(value: Value<S>) -> Option<Vec<T>> {
match value {
Value::List(vs) => {
let len = vs.len();
let extracted : Vec<T> = vs.into_iter().flat_map(T::extract).collect();
if extracted.len() < len {
None
} else {
Some(extracted)
}
},
_ => None,
}
}
pub fn extract_list_mut<S, T: ExtractMut<S>>(value: &mut Value<S>) -> Option<Vec<&mut T>> {
match value {
Value::List(vs) => {
let len = vs.len();
let extracted : Vec<&mut T> = vs.iter_mut().flat_map(T::extract_mut).collect();
if extracted.len() < len {
None
} else {
Some(extracted)
}
},
_ => None,
}
}