use std::collections::BTreeMap;
use std::fmt;
use base64::Engine;
use serde::de::{MapAccess, SeqAccess, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::Value;
impl Serialize for Value {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Value::Null => serializer.serialize_none(),
Value::Bool(value) => serializer.serialize_bool(*value),
Value::Int(value) => serializer.serialize_i64(*value),
Value::Float(value) => serializer.serialize_f64(*value),
Value::String(value) => serializer.serialize_str(value),
Value::Bytes(bytes) => {
if serializer.is_human_readable() {
serializer
.serialize_str(&base64::engine::general_purpose::STANDARD.encode(bytes))
} else {
serializer.serialize_bytes(bytes)
}
}
Value::List(items) => serializer.collect_seq(items),
Value::Map(map) => serializer.collect_map(map),
}
}
}
impl<'de> Deserialize<'de> for Value {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Value, D::Error> {
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 JSON-shaped value")
}
fn visit_unit<E>(self) -> Result<Value, E> {
Ok(Value::Null)
}
fn visit_none<E>(self) -> Result<Value, E> {
Ok(Value::Null)
}
fn visit_some<D: Deserializer<'de>>(self, deserializer: D) -> Result<Value, D::Error> {
deserializer.deserialize_any(ValueVisitor)
}
fn visit_bool<E>(self, value: bool) -> Result<Value, E> {
Ok(Value::Bool(value))
}
fn visit_i64<E>(self, value: i64) -> Result<Value, E> {
Ok(Value::Int(value))
}
fn visit_u64<E>(self, value: u64) -> Result<Value, E> {
Ok(match i64::try_from(value) {
Ok(value) => Value::Int(value),
Err(_) => Value::Float(value as f64),
})
}
fn visit_i128<E>(self, value: i128) -> Result<Value, E> {
Ok(match i64::try_from(value) {
Ok(value) => Value::Int(value),
Err(_) => Value::Float(value as f64),
})
}
fn visit_u128<E>(self, value: u128) -> Result<Value, E> {
Ok(match i64::try_from(value) {
Ok(value) => Value::Int(value),
Err(_) => Value::Float(value as f64),
})
}
fn visit_f64<E>(self, value: f64) -> Result<Value, E> {
Ok(Value::Float(value))
}
fn visit_str<E>(self, value: &str) -> Result<Value, E> {
Ok(Value::String(value.to_owned()))
}
fn visit_string<E>(self, value: String) -> Result<Value, E> {
Ok(Value::String(value))
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Value, E> {
Ok(Value::Bytes(value.to_vec()))
}
fn visit_byte_buf<E>(self, value: Vec<u8>) -> Result<Value, E> {
Ok(Value::Bytes(value))
}
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Value, A::Error> {
let mut items = Vec::with_capacity(seq.size_hint().unwrap_or(0));
while let Some(item) = seq.next_element()? {
items.push(item);
}
Ok(Value::List(items))
}
fn visit_map<A: MapAccess<'de>>(self, mut access: A) -> Result<Value, A::Error> {
let mut map = BTreeMap::new();
while let Some((key, value)) = access.next_entry::<String, Value>()? {
map.insert(key, value);
}
Ok(Value::Map(map))
}
}