use super::value::Value;
pub enum KVP<'a> {
Owned {
key: Value,
value: Value
},
Borrowed {
key: Value,
value: &'a Value
}
}
impl<'a> KVP<'a> {
pub fn key(&self) -> &Value {
match self {
KVP::Owned { key, .. } => key,
KVP::Borrowed { key, .. } => key,
}
}
pub fn value(&self) -> &Value {
match self {
KVP::Owned { value, .. } => value,
KVP::Borrowed { value, .. } => value,
}
}
pub fn into_owned(self) -> (Value, Value) {
match self {
KVP::Owned { key, value } => (key, value),
KVP::Borrowed { key, value } => (key, value.clone()),
}
}
}
pub struct IterBorrowed<'a> {
source: &'a Value,
pos: usize,
dict_keys: Option<Vec<&'a String>>,
}
pub struct IterOwned {
source: Value,
pos: usize,
dict_keys: Option<Vec<String>>,
}
impl<'a> Iterator for IterBorrowed<'a> {
type Item = KVP<'a>;
fn next(&mut self) -> Option<Self::Item> {
match self.source {
Value::Boolean(_) | Value::Numerical(_) | Value::Str(_) => {
if self.pos == 0 {
self.pos += 1; Some(KVP::Borrowed {
key: Value::Numerical(0.0),
value: self.source,
})
} else {
None
}
},
Value::List(values) => {
if self.pos < values.len() {
let key = Value::Numerical(self.pos as f64);
let value = &values[self.pos];
self.pos += 1;
Some(KVP::Borrowed { key, value })
} else {
None
}
},
Value::Dict(map) => {
if self.dict_keys.is_none() {
self.dict_keys = Some(map.keys().collect());
}
if let Some(keys) = &self.dict_keys {
if self.pos < keys.len() {
let key = keys[self.pos];
let value = map.get(key).unwrap();
let kvp = KVP::Borrowed {
key: Value::Str(key.clone()),
value,
};
self.pos += 1;
Some(kvp)
} else {
None
}
} else {
None
}
},
Value::None => None,
}
}
}
impl Iterator for IterOwned {
type Item = KVP<'static>;
fn next(&mut self) -> Option<Self::Item> {
match &mut self.source {
Value::Boolean(_) | Value::Numerical(_) | Value::Str(_) => {
if self.pos == 0 {
self.pos += 1; Some(KVP::Owned {
key: Value::Numerical(0.0),
value: std::mem::replace(&mut self.source, Value::None),
})
} else {
None
}
},
Value::List(values) => {
if self.pos < values.len() {
let key = Value::Numerical(self.pos as f64);
let value = std::mem::replace(&mut values[self.pos], Value::None);
self.pos += 1;
Some(KVP::Owned { key, value })
} else {
None
}
},
Value::Dict(map) => {
if self.dict_keys.is_none() {
self.dict_keys = Some(map.keys().cloned().collect());
}
if let Some(keys) = &self.dict_keys {
if self.pos < keys.len() {
let key = keys[self.pos].clone();
let value = map.remove(&key).unwrap_or(Value::None);
self.pos += 1;
Some(KVP::Owned {
key: Value::Str(key),
value,
})
} else {
None
}
} else {
None
}
},
Value::None => None,
}
}
}
impl Value {
pub fn iter(&self) -> IterBorrowed<'_> {
IterBorrowed {
source: self,
pos: 0,
dict_keys: None,
}
}
pub fn iter_owned(self) -> IterOwned {
IterOwned {
source: self,
pos: 0,
dict_keys: None,
}
}
}
impl<'a> IntoIterator for &'a Value {
type Item = KVP<'a>;
type IntoIter = IterBorrowed<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl IntoIterator for Value {
type Item = KVP<'static>;
type IntoIter = IterOwned;
fn into_iter(self) -> Self::IntoIter {
self.iter_owned()
}
}