use std::borrow::Cow;
use std::fmt::Debug;
use crate::types::ObjectKey;
use crate::{
error::Error,
reader::Reader,
types::Date,
types::{CollectionType, RealType},
};
pub type ObjectEntry<'src> = (ObjectKey<'src>, Value<'src>);
pub type ObjectMap<'src> = Vec<ObjectEntry<'src>>;
#[derive(Debug, PartialEq, PartialOrd, Clone)]
pub enum Value<'src> {
None,
Integer(i64),
Decimal(f64),
Boolean(bool),
Date(Date),
String(Cow<'src, str>),
Identifier(Cow<'src, str>),
Object(ObjectMap<'src>),
Array(Vec<Value<'src>>),
}
impl<'reader, 'src: 'reader> Value<'src> {
pub fn from_reader(reader: &'reader mut Reader<'src>) -> Result<Value<'src>, Error> {
let mut values = Vec::new();
while let Some((name, _)) = reader.next_property()? {
values.push((name.into(), Self::next_from_reader(reader)?))
}
return Ok(Self::Object(values));
}
pub fn next_from_reader(reader: &'reader mut Reader<'src>) -> Result<Value<'src>, Error> {
let next = reader.peek_next_type()?;
if next.is_none() {
return Ok(Self::None);
}
let next = next.unwrap();
match next {
RealType::Boolean => Ok(Self::Boolean(reader.read_boolean()?)),
RealType::Identifier => Ok(Self::Identifier(reader.read_identifier()?.into())),
RealType::String => Ok(Self::String(reader.read_string()?.into())),
RealType::Number => Ok({
let number = reader.read_number_as_str()?;
match number.contains(".") {
true => Self::Decimal(reader.parse_number(number)?),
false => Self::Integer(reader.parse_number(number)?),
}
}),
RealType::Date => Ok(Self::Date(reader.read_date()?)),
RealType::ObjectOrArray => {
let collection_type = reader.try_discern_array_or_map()?;
if collection_type.is_none() {
return Ok(Self::None);
}
match collection_type.unwrap() {
CollectionType::Array => {
reader.begin_collection()?;
let mut values = Vec::new();
while !reader.is_collection_ended()? {
values.push(Self::next_from_reader(reader)?)
}
reader.end_collection()?;
Ok(Self::Array(values))
}
CollectionType::Object => {
reader.begin_collection()?;
let mut values = Vec::new();
while let Some((name, _)) = reader.next_property()? {
values.push((name.into(), Self::next_from_reader(reader)?));
}
reader.end_collection()?;
Ok(Self::Object(values))
}
}
}
}
}
pub fn from_str(s: &'src str) -> Result<Value<'src>, Error> {
let mut reader = Reader::new(s);
Value::from_reader(&mut reader)
}
}