use std::{collections::BTreeMap, fmt};
use serde::{Deserialize, de, ser};
use crate::cid::{BytesToCidVisitor, Cid};
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum Value {
Integer(i128),
Bytes(Vec<u8>),
Float(f64),
Text(String),
Bool(bool),
Null,
Cid(Cid),
Array(Vec<Value>),
Map(BTreeMap<String, Value>),
}
impl From<String> for Value {
fn from(value: String) -> Self {
Self::Text(value)
}
}
impl From<Cid> for Value {
fn from(value: Cid) -> Self {
Self::Cid(value)
}
}
impl From<bool> for Value {
fn from(value: bool) -> Self {
Self::Bool(value)
}
}
impl From<u32> for Value {
fn from(value: u32) -> Self {
Self::Integer(i128::from(value))
}
}
impl From<u64> for Value {
fn from(value: u64) -> Self {
Self::Integer(i128::from(value))
}
}
impl From<i32> for Value {
fn from(value: i32) -> Self {
Self::Integer(i128::from(value))
}
}
impl From<i64> for Value {
fn from(value: i64) -> Self {
Self::Integer(i128::from(value))
}
}
impl From<i128> for Value {
fn from(value: i128) -> Self {
Self::Integer(value)
}
}
impl From<Vec<u8>> for Value {
fn from(value: Vec<u8>) -> Self {
Self::Bytes(value)
}
}
impl From<f64> for Value {
fn from(value: f64) -> Self {
Self::Float(value)
}
}
impl<'de> de::Deserialize<'de> for Value {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct ValueVisitor;
impl<'de> de::Visitor<'de> for ValueVisitor {
type Value = Value;
fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.write_str("any valid DRISL kind")
}
#[inline]
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Value::Text(String::from(value)))
}
#[inline]
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_byte_buf(v.to_owned())
}
#[inline]
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Value::Bytes(v))
}
#[inline]
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Value::Integer(v.into()))
}
#[inline]
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Value::Integer(v.into()))
}
#[inline]
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Value::Integer(v))
}
#[inline]
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Value::Float(v))
}
#[inline]
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Value::Bool(v))
}
#[inline]
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Value::Null)
}
#[inline]
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: de::Deserializer<'de>,
{
Deserialize::deserialize(deserializer)
}
#[inline]
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Value::Null)
}
#[inline]
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: de::SeqAccess<'de>,
{
let mut vec = Vec::with_capacity(visitor.size_hint().unwrap_or(0));
while let Some(elem) = visitor.next_element()? {
vec.push(elem);
}
Ok(Value::Array(vec))
}
#[inline]
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: de::MapAccess<'de>,
{
let mut values = BTreeMap::new();
while let Some((key, value)) = visitor.next_entry()? {
let prev_value = values.insert(key, value);
if prev_value.is_some() {
return Err(de::Error::custom("Duplicate map key"));
}
}
Ok(Value::Map(values))
}
#[inline]
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: de::Deserializer<'de>,
{
deserializer
.deserialize_bytes(BytesToCidVisitor)
.map(Value::Cid)
}
}
deserializer.deserialize_any(ValueVisitor)
}
}
impl ser::Serialize for Value {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
match &self {
Self::Null => serializer.serialize_none(),
Self::Bool(value) => serializer.serialize_bool(*value),
Self::Integer(value) => serializer.serialize_i128(*value),
Self::Float(value) => serializer.serialize_f64(*value),
Self::Text(value) => serializer.serialize_str(value),
Self::Bytes(value) => serializer.serialize_bytes(value),
Self::Array(value) => serializer.collect_seq(value),
Self::Map(value) => serializer.collect_map(value),
Self::Cid(value) => value.serialize(serializer),
}
}
}