use crate::error::Error;
use forma_core::de::{Deserialize, DeserializeOwned, Deserializer, MapAccess, SeqAccess, Visitor};
use forma_core::error::DeError;
use forma_core::ser::{self, Serialize, Serializer};
use std::collections::BTreeMap;
use std::fmt;
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Null,
Bool(bool),
Number(Number),
String(String),
Array(Vec<Value>),
Object(BTreeMap<String, Value>),
}
#[derive(Debug, Clone)]
pub enum Number {
PosInt(u64),
NegInt(i64),
Float(f64),
}
impl PartialEq for Number {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Number::PosInt(a), Number::PosInt(b)) => a == b,
(Number::NegInt(a), Number::NegInt(b)) => a == b,
(Number::Float(a), Number::Float(b)) => a.to_bits() == b.to_bits(),
_ => false,
}
}
}
impl Number {
pub fn as_f64(&self) -> f64 {
match *self {
Number::PosInt(v) => v as f64,
Number::NegInt(v) => v as f64,
Number::Float(v) => v,
}
}
pub fn as_i64(&self) -> Option<i64> {
match *self {
Number::PosInt(v) => i64::try_from(v).ok(),
Number::NegInt(v) => Some(v),
Number::Float(_) => None,
}
}
pub fn as_u64(&self) -> Option<u64> {
match *self {
Number::PosInt(v) => Some(v),
Number::NegInt(_) => None,
Number::Float(_) => None,
}
}
pub fn is_f64(&self) -> bool {
matches!(self, Number::Float(_))
}
}
impl fmt::Display for Number {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Number::PosInt(v) => write!(f, "{v}"),
Number::NegInt(v) => write!(f, "{v}"),
Number::Float(v) => write!(f, "{v}"),
}
}
}
impl Value {
pub fn is_null(&self) -> bool {
matches!(self, Value::Null)
}
pub fn is_bool(&self) -> bool {
matches!(self, Value::Bool(_))
}
pub fn is_number(&self) -> bool {
matches!(self, Value::Number(_))
}
pub fn is_string(&self) -> bool {
matches!(self, Value::String(_))
}
pub fn is_array(&self) -> bool {
matches!(self, Value::Array(_))
}
pub fn is_object(&self) -> bool {
matches!(self, Value::Object(_))
}
pub fn as_bool(&self) -> Option<bool> {
match self {
Value::Bool(b) => Some(*b),
_ => None,
}
}
pub fn as_f64(&self) -> Option<f64> {
match self {
Value::Number(n) => Some(n.as_f64()),
_ => None,
}
}
pub fn as_i64(&self) -> Option<i64> {
match self {
Value::Number(n) => n.as_i64(),
_ => None,
}
}
pub fn as_u64(&self) -> Option<u64> {
match self {
Value::Number(n) => n.as_u64(),
_ => None,
}
}
pub fn as_str(&self) -> Option<&str> {
match self {
Value::String(s) => Some(s),
_ => None,
}
}
pub fn as_array(&self) -> Option<&Vec<Value>> {
match self {
Value::Array(a) => Some(a),
_ => None,
}
}
pub fn as_object(&self) -> Option<&BTreeMap<String, Value>> {
match self {
Value::Object(m) => Some(m),
_ => None,
}
}
pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> {
match self {
Value::Array(a) => Some(a),
_ => None,
}
}
pub fn as_object_mut(&mut self) -> Option<&mut BTreeMap<String, Value>> {
match self {
Value::Object(m) => Some(m),
_ => None,
}
}
pub fn get(&self, key: &str) -> Option<&Value> {
self.as_object()?.get(key)
}
pub fn get_index(&self, index: usize) -> Option<&Value> {
self.as_array()?.get(index)
}
}
impl std::ops::Index<&str> for Value {
type Output = Value;
fn index(&self, key: &str) -> &Value {
static NULL: Value = Value::Null;
self.get(key).unwrap_or(&NULL)
}
}
impl std::ops::Index<usize> for Value {
type Output = Value;
fn index(&self, index: usize) -> &Value {
static NULL: Value = Value::Null;
self.get_index(index).unwrap_or(&NULL)
}
}
impl From<bool> for Value {
fn from(v: bool) -> Self {
Value::Bool(v)
}
}
impl From<i32> for Value {
fn from(v: i32) -> Self {
if v >= 0 {
Value::Number(Number::PosInt(v as u64))
} else {
Value::Number(Number::NegInt(v as i64))
}
}
}
impl From<i64> for Value {
fn from(v: i64) -> Self {
if v >= 0 {
Value::Number(Number::PosInt(v as u64))
} else {
Value::Number(Number::NegInt(v))
}
}
}
impl From<u64> for Value {
fn from(v: u64) -> Self {
Value::Number(Number::PosInt(v))
}
}
impl From<f64> for Value {
fn from(v: f64) -> Self {
Value::Number(Number::Float(v))
}
}
impl From<String> for Value {
fn from(v: String) -> Self {
Value::String(v)
}
}
impl From<&str> for Value {
fn from(v: &str) -> Self {
Value::String(v.to_string())
}
}
impl<T: Into<Value>> From<Vec<T>> for Value {
fn from(v: Vec<T>) -> Self {
Value::Array(v.into_iter().map(Into::into).collect())
}
}
impl From<()> for Value {
fn from(_: ()) -> Self {
Value::Null
}
}
impl<T: Into<Value>> From<Option<T>> for Value {
fn from(v: Option<T>) -> Self {
match v {
Some(v) => v.into(),
None => Value::Null,
}
}
}
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match crate::to_string(self) {
Ok(s) => f.write_str(&s),
Err(_) => Err(fmt::Error),
}
}
}
impl Serialize for Value {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Value::Null => serializer.serialize_unit(),
Value::Bool(b) => serializer.serialize_bool(*b),
Value::Number(Number::PosInt(v)) => serializer.serialize_u64(*v),
Value::Number(Number::NegInt(v)) => serializer.serialize_i64(*v),
Value::Number(Number::Float(v)) => serializer.serialize_f64(*v),
Value::String(s) => serializer.serialize_str(s),
Value::Array(arr) => {
let mut seq = serializer.serialize_seq(Some(arr.len()))?;
for item in arr {
ser::SerializeSeq::serialize_element(&mut seq, item)?;
}
ser::SerializeSeq::end(seq)
}
Value::Object(map) => {
let mut m = serializer.serialize_map(Some(map.len()))?;
for (key, value) in map {
ser::SerializeMap::serialize_entry(&mut m, key, value)?;
}
ser::SerializeMap::end(m)
}
}
}
}
impl<'de> Deserialize<'de> for Value {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_any(ValueVisitor)
}
}
struct ValueVisitor;
impl<'de> Visitor<'de> for ValueVisitor {
type Value = Value;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("any JSON value")
}
fn visit_bool<E: DeError>(self, v: bool) -> Result<Value, E> {
Ok(Value::Bool(v))
}
fn visit_i64<E: DeError>(self, v: i64) -> Result<Value, E> {
Ok(Value::from(v))
}
fn visit_u64<E: DeError>(self, v: u64) -> Result<Value, E> {
Ok(Value::Number(Number::PosInt(v)))
}
fn visit_f64<E: DeError>(self, v: f64) -> Result<Value, E> {
Ok(Value::Number(Number::Float(v)))
}
fn visit_str<E: DeError>(self, v: &str) -> Result<Value, E> {
Ok(Value::String(v.to_string()))
}
fn visit_string<E: DeError>(self, v: String) -> Result<Value, E> {
Ok(Value::String(v))
}
fn visit_none<E: DeError>(self) -> Result<Value, E> {
Ok(Value::Null)
}
fn visit_unit<E: DeError>(self) -> Result<Value, E> {
Ok(Value::Null)
}
fn visit_some<D: Deserializer<'de>>(self, deserializer: D) -> Result<Value, D::Error> {
Value::deserialize(deserializer)
}
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Value, A::Error> {
let mut arr = Vec::new();
while let Some(elem) = seq.next_element::<Value>()? {
arr.push(elem);
}
Ok(Value::Array(arr))
}
fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Value, A::Error> {
let mut obj = BTreeMap::new();
while let Some((key, value)) = map.next_entry::<String, Value>()? {
obj.insert(key, value);
}
Ok(Value::Object(obj))
}
}
pub fn from_value<T: DeserializeOwned>(value: Value) -> Result<T, Error> {
let s = crate::to_string(&value)?;
crate::from_str(&s)
}
pub fn to_value<T: Serialize>(value: &T) -> Result<Value, Error> {
let s = crate::to_string(value)?;
crate::from_str(&s)
}