Add for loop
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
7182024342
commit
42e0056374
16 changed files with 775 additions and 44 deletions
251
src/value.rs
Normal file
251
src/value.rs
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[cfg(feature = "serde_json")]
|
||||
use displaydoc::Display;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum NomoValue {
|
||||
String {
|
||||
value: Cow<'static, str>,
|
||||
},
|
||||
Array {
|
||||
value: Vec<NomoValue>,
|
||||
},
|
||||
Bool {
|
||||
value: bool,
|
||||
},
|
||||
Object {
|
||||
value: BTreeMap<String, NomoValue>,
|
||||
},
|
||||
Integer {
|
||||
value: u64,
|
||||
},
|
||||
SignedInteger {
|
||||
value: i64,
|
||||
},
|
||||
Float {
|
||||
value: f64,
|
||||
},
|
||||
Iterator {
|
||||
value: Box<dyn CloneIterator<Item = NomoValue>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl NomoValue {
|
||||
pub fn as_str(&self) -> Option<&str> {
|
||||
if let Self::String { value } = self {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_array(&self) -> Option<&[NomoValue]> {
|
||||
if let Self::Array { value } = self {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_bool(&self) -> Option<bool> {
|
||||
if let Self::Bool { value } = self {
|
||||
Some(*value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_object(&self) -> Option<&BTreeMap<String, NomoValue>> {
|
||||
if let Self::Object { value } = self {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_integer(&self) -> Option<u64> {
|
||||
if let Self::Integer { value } = self {
|
||||
Some(*value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_float(&self) -> Option<f64> {
|
||||
if let Self::Float { value } = self {
|
||||
Some(*value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_iterator(&self) -> Option<&dyn CloneIterator<Item = NomoValue>> {
|
||||
if let Self::Iterator { value } = self {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_iterator_mut(&mut self) -> Option<&mut dyn CloneIterator<Item = NomoValue>> {
|
||||
if let Self::Iterator { value } = self {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CloneIterator: Iterator<Item = NomoValue> {
|
||||
fn clone_box(&self) -> Box<dyn CloneIterator<Item = NomoValue>>;
|
||||
}
|
||||
|
||||
impl<I> CloneIterator for I
|
||||
where
|
||||
I: Iterator<Item = NomoValue> + Clone + 'static,
|
||||
{
|
||||
fn clone_box(&self) -> Box<dyn CloneIterator<Item = NomoValue>> {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Box<dyn CloneIterator> {
|
||||
fn clone(&self) -> Self {
|
||||
self.clone_box()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for NomoValue {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::String { value } => f.debug_struct("String").field("value", value).finish(),
|
||||
Self::Array { value } => f.debug_struct("Array").field("value", value).finish(),
|
||||
Self::Bool { value } => f.debug_struct("Bool").field("value", value).finish(),
|
||||
Self::Object { value } => f.debug_struct("Object").field("value", value).finish(),
|
||||
Self::Integer { value } => f.debug_struct("Integer").field("value", value).finish(),
|
||||
Self::SignedInteger { value } => f
|
||||
.debug_struct("SignedInteger")
|
||||
.field("value", value)
|
||||
.finish(),
|
||||
Self::Float { value } => f.debug_struct("Float").field("value", value).finish(),
|
||||
Self::Iterator { value: _ } => f
|
||||
.debug_struct("Iterator")
|
||||
.field("value", &"Iterator")
|
||||
.finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> From<&R> for NomoValue
|
||||
where
|
||||
R: Into<NomoValue> + Clone,
|
||||
{
|
||||
fn from(value: &R) -> Self {
|
||||
value.clone().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for NomoValue {
|
||||
fn from(val: String) -> Self {
|
||||
NomoValue::String {
|
||||
value: Cow::Owned(val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&'static str> for NomoValue {
|
||||
fn from(val: &'static str) -> Self {
|
||||
NomoValue::String {
|
||||
value: Cow::Borrowed(val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> From<Vec<V>> for NomoValue
|
||||
where
|
||||
V: Into<NomoValue>,
|
||||
{
|
||||
fn from(val: Vec<V>) -> Self {
|
||||
NomoValue::Array {
|
||||
value: val.into_iter().map(Into::into).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> From<std::collections::VecDeque<V>> for NomoValue
|
||||
where
|
||||
V: Into<NomoValue>,
|
||||
{
|
||||
fn from(val: std::collections::VecDeque<V>) -> Self {
|
||||
NomoValue::Array {
|
||||
value: val.into_iter().map(Into::into).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> From<&[V]> for NomoValue
|
||||
where
|
||||
V: Into<NomoValue> + Clone,
|
||||
{
|
||||
fn from(value: &[V]) -> Self {
|
||||
NomoValue::Array {
|
||||
value: value.iter().cloned().map(Into::into).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> From<std::collections::HashMap<K, V>> for NomoValue
|
||||
where
|
||||
K: Into<String>,
|
||||
V: Into<NomoValue>,
|
||||
{
|
||||
fn from(val: std::collections::HashMap<K, V>) -> Self {
|
||||
NomoValue::Object {
|
||||
value: val.into_iter().map(|(k, v)| (k.into(), v.into())).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde_json")]
|
||||
#[derive(Debug, Error, Display)]
|
||||
/// Could not transform value to [`NomoValue`]
|
||||
pub struct NomoValueError;
|
||||
|
||||
#[cfg(feature = "serde_json")]
|
||||
impl TryFrom<serde_json::Value> for NomoValue {
|
||||
type Error = NomoValueError;
|
||||
fn try_from(value: serde_json::Value) -> Result<Self, NomoValueError> {
|
||||
match value {
|
||||
serde_json::Value::Null => todo!(),
|
||||
serde_json::Value::Bool(value) => Ok(NomoValue::Bool { value }),
|
||||
serde_json::Value::Number(number) => {
|
||||
if let Some(value) = number.as_u64() {
|
||||
return Ok(NomoValue::Integer { value });
|
||||
}
|
||||
|
||||
if let Some(value) = number.as_f64() {
|
||||
return Ok(NomoValue::Float { value });
|
||||
}
|
||||
|
||||
if let Some(value) = number.as_i64() {
|
||||
return Ok(NomoValue::SignedInteger { value });
|
||||
}
|
||||
|
||||
Err(NomoValueError)
|
||||
}
|
||||
serde_json::Value::String(str) => Ok(NomoValue::String {
|
||||
value: Cow::Owned(str),
|
||||
}),
|
||||
serde_json::Value::Array(values) => Ok(NomoValue::Array {
|
||||
value: values
|
||||
.into_iter()
|
||||
.map(TryInto::try_into)
|
||||
.collect::<Result<_, _>>()?,
|
||||
}),
|
||||
serde_json::Value::Object(_map) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue