use crate::{Exportable, Serializable};
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Visitor};
use std::collections::BTreeMap;
use std::fmt;
#[derive(Debug, Default, Clone, PartialEq)]
pub enum Value {
#[default]
Null,
Bool(bool),
Number(NumberValue),
String(String),
Array(Vec<Self>),
Object(BTreeMap<String, Self>),
}
#[derive(Debug, Clone, PartialEq)]
pub enum NumberValue {
PosInt(u64),
NegInt(i64),
Float(f64),
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub(crate) struct AnySchema {
metadata: Option<crate::MetadataSchema>,
}
impl Serializable for AnySchema {
fn serialize(&self) -> Option<String> {
if let Some(ref metadata) = self.metadata {
crate::Serializer::builder()
.set("metadata", metadata)
.build()
.into()
} else {
Some("{}".to_string())
}
}
fn set_metadata(&mut self, metadata: crate::MetadataSchema) {
self.metadata = Some(metadata);
}
}
impl Exportable for Value {
fn export_internal() -> impl Serializable {
AnySchema::default()
}
}
impl Serialize for Value {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Self::Null => serializer.serialize_none(),
Self::Bool(b) => serializer.serialize_bool(*b),
Self::Number(n) => n.serialize(serializer),
Self::String(s) => serializer.serialize_str(s),
Self::Array(arr) => arr.serialize(serializer),
Self::Object(obj) => obj.serialize(serializer),
}
}
}
impl Serialize for NumberValue {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Self::PosInt(n) => serializer.serialize_u64(*n),
Self::NegInt(n) => serializer.serialize_i64(*n),
Self::Float(n) => serializer.serialize_f64(*n),
}
}
}
impl<'de> Deserialize<'de> for Value {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(ValueVisitor)
}
}
struct ValueVisitor;
impl<'de> Visitor<'de> for ValueVisitor {
type Value = Value;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("any valid JSON value")
}
fn visit_unit<E>(self) -> Result<Self::Value, E> {
Ok(Value::Null)
}
fn visit_none<E>(self) -> Result<Self::Value, E> {
Ok(Value::Null)
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
Deserialize::deserialize(deserializer)
}
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E> {
Ok(Value::Bool(v))
}
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E> {
if v >= 0 {
Ok(Value::Number(NumberValue::PosInt(v as u64)))
} else {
Ok(Value::Number(NumberValue::NegInt(v)))
}
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
Ok(Value::Number(NumberValue::PosInt(v)))
}
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E> {
Ok(Value::Number(NumberValue::Float(v)))
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::String(v.to_string()))
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E> {
Ok(Value::String(v))
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let mut vec = Vec::new();
while let Some(elem) = seq.next_element()? {
vec.push(elem);
}
Ok(Value::Array(vec))
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let mut btree = BTreeMap::new();
while let Some((key, value)) = map.next_entry()? {
btree.insert(key, value);
}
Ok(Value::Object(btree))
}
}
impl<'de> Deserialize<'de> for NumberValue {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(NumberVisitor)
}
}
struct NumberVisitor;
impl<'de> Visitor<'de> for NumberVisitor {
type Value = NumberValue;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a JSON number")
}
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E> {
if v >= 0 {
Ok(NumberValue::PosInt(v as u64))
} else {
Ok(NumberValue::NegInt(v))
}
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
Ok(NumberValue::PosInt(v))
}
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E> {
Ok(NumberValue::Float(v))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_any_schema_serializes_to_empty_object() {
let schema = AnySchema::default();
assert_eq!(schema.serialize(), Some("{}".to_string()));
}
#[test]
fn test_value_export_returns_any_schema() {
let export = Value::export();
assert_eq!(export.serialize(), Some("{}".to_string()));
}
}