Add for loop

Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
Marcel Müller 2026-03-11 18:09:58 +01:00
parent 7182024342
commit 42e0056374
16 changed files with 775 additions and 44 deletions

251
src/value.rs Normal file
View 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!(),
}
}
}