use std::borrow::Cow;
use std::fmt::{Display, Write};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use serde::de::{EnumAccess, MapAccess, SeqAccess, VariantAccess, Visitor};
use serde::ser::{
SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
SerializeTupleStruct, SerializeTupleVariant,
};
use serde::{Deserialize, Serialize};
use crate::format::{Float, InnerFloat, InnerInteger, Integer};
#[derive(Debug, Clone)]
pub enum Value<'a> {
None,
Unit,
Bool(bool),
Integer(Integer),
Float(Float),
Bytes(Cow<'a, [u8]>),
String(Cow<'a, str>),
Sequence(Vec<Self>),
Mappings(Vec<(Self, Self)>),
}
impl<'a> Value<'a> {
#[inline]
pub fn from_serialize<T: Serialize>(value: T) -> Result<Self, ValueError> {
value.serialize(Serializer)
}
#[inline]
pub fn deserialize_as<'de, T: Deserialize<'de>>(&'de self) -> Result<T, ValueError> {
T::deserialize(Deserializer(self))
}
#[inline]
pub fn from_sequence<IntoIter: IntoIterator<Item = T>, T: Into<Self>>(
sequence: IntoIter,
) -> Self {
Self::from_iter(sequence)
}
#[inline]
pub fn from_mappings<IntoIter: IntoIterator<Item = (K, V)>, K: Into<Self>, V: Into<Self>>(
mappings: IntoIter,
) -> Self {
Self::from_iter(mappings)
}
#[must_use]
#[inline]
pub fn is_empty(&self) -> bool {
match self {
Value::None => true,
Value::Unit | Value::Bool(_) | Value::Integer(_) | Value::Float(_) => false,
Value::Bytes(value) => value.is_empty(),
Value::String(value) => value.is_empty(),
Value::Sequence(value) => value.is_empty(),
Value::Mappings(value) => value.is_empty(),
}
}
#[must_use]
#[inline]
pub fn as_bool(&self) -> bool {
match self {
Value::None => false,
Value::Unit => true,
Value::Bool(value) => *value,
Value::Integer(value) => !value.is_zero(),
Value::Float(value) => !value.is_zero(),
Value::Bytes(value) => !value.is_empty(),
Value::String(value) => !value.is_empty(),
Value::Sequence(value) => !value.is_empty(),
Value::Mappings(value) => !value.is_empty(),
}
}
#[must_use]
#[inline]
pub fn as_integer(&self) -> Option<Integer> {
match self {
Value::Integer(value) => Some(*value),
Value::Float(value) => value.as_integer().ok(),
_ => None,
}
}
#[must_use]
#[inline]
pub fn as_float(&self) -> Option<Float> {
match self {
Value::Integer(value) => value.as_float().ok(),
Value::Float(value) => Some(*value),
_ => None,
}
}
#[must_use]
#[inline]
pub fn as_str(&self) -> Option<&str> {
match self {
Self::Bytes(bytes) => std::str::from_utf8(bytes).ok(),
Self::String(string) => Some(string),
_ => None,
}
}
#[must_use]
#[inline]
pub fn as_bytes(&self) -> Option<&[u8]> {
match self {
Self::Bytes(bytes) => Some(bytes),
Self::String(string) => Some(string.as_bytes()),
_ => None,
}
}
#[must_use]
#[inline]
pub fn values(&self) -> ValueIter<'_> {
match self {
Self::Sequence(sequence) => ValueIter(SequenceIterState::Sequence(sequence.iter())),
Self::Mappings(mappings) => ValueIter(SequenceIterState::Mappings(mappings.iter())),
_ => ValueIter(SequenceIterState::Sequence([].iter())),
}
}
#[inline]
pub fn mappings(&self) -> std::slice::Iter<'_, (Self, Self)> {
match self {
Self::Mappings(mappings) => mappings.iter(),
_ => [].iter(),
}
}
pub fn into_static(self) -> Value<'static> {
match self {
Self::None => Value::None,
Self::Unit => Value::Unit,
Self::Bool(value) => Value::Bool(value),
Self::Integer(value) => Value::Integer(value),
Self::Float(value) => Value::Float(value),
Self::Bytes(Cow::Owned(value)) => Value::Bytes(Cow::Owned(value)),
Self::Bytes(Cow::Borrowed(value)) => Value::Bytes(Cow::Owned(value.to_vec())),
Self::String(Cow::Owned(value)) => Value::String(Cow::Owned(value)),
Self::String(Cow::Borrowed(value)) => Value::String(Cow::Owned(value.to_string())),
Self::Sequence(value) => {
Value::Sequence(value.into_iter().map(Value::into_static).collect())
}
Self::Mappings(value) => Value::Mappings(
value
.into_iter()
.map(|(k, v)| (k.into_static(), v.into_static()))
.collect(),
),
}
}
pub fn to_static(&self) -> Value<'static> {
match self {
Self::None => Value::None,
Self::Unit => Value::Unit,
Self::Bool(value) => Value::Bool(*value),
Self::Integer(value) => Value::Integer(*value),
Self::Float(value) => Value::Float(*value),
Self::Bytes(Cow::Owned(value)) => Value::Bytes(Cow::Owned(value.clone())),
Self::Bytes(Cow::Borrowed(value)) => Value::Bytes(Cow::Owned(value.to_vec())),
Self::String(Cow::Owned(value)) => Value::String(Cow::Owned(value.clone())),
Self::String(Cow::Borrowed(value)) => Value::String(Cow::Owned((*value).to_string())),
Self::Sequence(value) => Value::Sequence(value.iter().map(Value::to_static).collect()),
Self::Mappings(value) => Value::Mappings(
value
.iter()
.map(|(k, v)| (k.to_static(), v.to_static()))
.collect(),
),
}
}
}
impl<'a, 'b> PartialEq<Value<'b>> for Value<'a> {
#[inline]
fn eq(&self, other: &Value<'b>) -> bool {
match (self, other) {
(Self::Bool(l0), Value::Bool(r0)) => l0 == r0,
(Self::Integer(l0), Value::Integer(r0)) => l0 == r0,
(Self::Float(l0), Value::Float(r0)) => l0 == r0,
(Self::Bytes(l0), Value::Bytes(r0)) => l0 == r0,
(Self::String(l0), Value::String(r0)) => l0 == r0,
(Self::Bytes(l0), Value::String(r0)) => *l0 == r0.as_bytes(),
(Self::String(l0), Value::Bytes(r0)) => l0.as_bytes() == &**r0,
(Self::Sequence(l0), Value::Sequence(r0)) => l0 == r0,
(Self::Mappings(l0), Value::Mappings(r0)) => l0 == r0,
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
}
}
}
impl<'a> Display for Value<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Value::None => f.write_str("None"),
Value::Unit => f.write_str("()"),
Value::Bool(true) => f.write_str("true"),
Value::Bool(false) => f.write_str("false"),
Value::Integer(value) => Display::fmt(value, f),
Value::Float(value) => Display::fmt(value, f),
Value::Bytes(bytes) => {
f.write_str("0x")?;
for (index, byte) in bytes.iter().enumerate() {
if index > 0 && index % 4 == 0 {
f.write_char('_')?;
}
write!(f, "{byte:02x}")?;
}
Ok(())
}
Value::String(string) => f.write_str(string),
Value::Sequence(sequence) => {
f.write_char('[')?;
for (index, value) in sequence.iter().enumerate() {
if index > 0 {
f.write_str(", ")?;
}
Display::fmt(value, f)?;
}
f.write_char(']')
}
Value::Mappings(mappings) => {
f.write_char('{')?;
for (index, (key, value)) in mappings.iter().enumerate() {
if index > 0 {
f.write_str(", ")?;
}
Display::fmt(key, f)?;
f.write_str(": ")?;
Display::fmt(value, f)?;
}
f.write_char('}')
}
}
}
}
impl<'a> Serialize for Value<'a> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
Value::None => serializer.serialize_none(),
Value::Unit => serializer.serialize_unit(),
Value::Bool(value) => serializer.serialize_bool(*value),
Value::Integer(integer) => match integer.0 {
InnerInteger::I8(value) => serializer.serialize_i8(value),
InnerInteger::I16(value) => serializer.serialize_i16(value),
InnerInteger::I32(value) => serializer.serialize_i32(value),
InnerInteger::I64(value) => serializer.serialize_i64(value),
InnerInteger::I128(value) => serializer.serialize_i128(value),
InnerInteger::U8(value) => serializer.serialize_u8(value),
InnerInteger::U16(value) => serializer.serialize_u16(value),
InnerInteger::U32(value) => serializer.serialize_u32(value),
InnerInteger::U64(value) => serializer.serialize_u64(value),
InnerInteger::U128(value) => serializer.serialize_u128(value),
},
Value::Float(value) => match value.0 {
InnerFloat::F64(value) => serializer.serialize_f64(value),
InnerFloat::F32(value) => serializer.serialize_f32(value),
},
Value::Bytes(value) => serializer.serialize_bytes(value),
Value::String(value) => serializer.serialize_str(value),
Value::Sequence(values) => {
let mut seq = serializer.serialize_seq(Some(values.len()))?;
for value in values {
seq.serialize_element(value)?;
}
seq.end()
}
Value::Mappings(keys_and_values) => {
let mut map = serializer.serialize_map(Some(keys_and_values.len()))?;
for (key, value) in keys_and_values {
map.serialize_entry(key, value)?;
}
map.end()
}
}
}
}
impl<'de: 'a, 'a> Deserialize<'de> for Value<'a> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_any(ValueVisitor::default())
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct OwnedValue(pub Value<'static>);
impl Deref for OwnedValue {
type Target = Value<'static>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for OwnedValue {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl Serialize for OwnedValue {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.0.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for OwnedValue {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer
.deserialize_any(ValueVisitor::default())
.map(|value| Self(value.into_static()))
}
}
impl<'a> From<Value<'a>> for OwnedValue {
#[inline]
fn from(value: Value<'a>) -> Self {
Self(value.into_static())
}
}
impl<'a> From<&'a Value<'a>> for OwnedValue {
#[inline]
fn from(value: &'a Value<'a>) -> Self {
Self(value.to_static())
}
}
#[derive(Default)]
struct ValueVisitor<'a>(PhantomData<&'a ()>);
impl<'de: 'a, 'a> Visitor<'de> for ValueVisitor<'a> {
type Value = Value<'a>;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("any value")
}
#[inline]
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::None)
}
#[inline]
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Bool(v))
}
#[inline]
fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Integer(Integer::from(v)))
}
#[inline]
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Integer(Integer::from(v)))
}
#[inline]
fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Integer(Integer::from(v)))
}
#[inline]
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Integer(Integer::from(v)))
}
#[inline]
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Integer(Integer::from(v)))
}
#[inline]
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Integer(Integer::from(v)))
}
#[inline]
fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Integer(Integer::from(v)))
}
#[inline]
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Integer(Integer::from(v)))
}
#[inline]
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Integer(Integer::from(v)))
}
#[inline]
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Integer(Integer::from(v)))
}
#[inline]
fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Float(Float::from(v)))
}
#[inline]
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Float(Float::from(v)))
}
#[inline]
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::String(Cow::Owned(v.to_string())))
}
#[inline]
fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::String(Cow::Borrowed(v)))
}
#[inline]
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::String(Cow::Owned(v)))
}
#[inline]
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Bytes(Cow::Owned(v.to_vec())))
}
#[inline]
fn visit_borrowed_bytes<E>(self, v: &'a [u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Bytes(Cow::Borrowed(v)))
}
#[inline]
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Bytes(Cow::Owned(v)))
}
#[inline]
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_any(Self::default())
}
#[inline]
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Value::Unit)
}
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let mut values = if let Some(hint) = seq.size_hint() {
Vec::with_capacity(hint)
} else {
Vec::new()
};
while let Some(value) = seq.next_element()? {
values.push(value);
}
Ok(Value::Sequence(values))
}
#[inline]
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let mut values = if let Some(hint) = map.size_hint() {
Vec::with_capacity(hint)
} else {
Vec::new()
};
while let Some(value) = map.next_entry()? {
values.push(value);
}
Ok(Value::Mappings(values))
}
}
impl<'a> From<Option<Value<'a>>> for Value<'a> {
#[inline]
fn from(value: Option<Value<'a>>) -> Self {
if let Some(value) = value {
value
} else {
Value::None
}
}
}
impl<'a> From<()> for Value<'a> {
#[inline]
fn from(_: ()) -> Self {
Value::Unit
}
}
impl<'a> From<bool> for Value<'a> {
#[inline]
fn from(value: bool) -> Self {
Value::Bool(value)
}
}
macro_rules! define_value_from_primitive {
($container:ident, $variant:ident, $primitive:ty) => {
impl<'a> From<$primitive> for Value<'a> {
#[inline]
fn from(value: $primitive) -> Self {
Self::$container($container::from(value))
}
}
};
}
define_value_from_primitive!(Integer, U8, u8);
define_value_from_primitive!(Integer, U16, u16);
define_value_from_primitive!(Integer, U32, u32);
define_value_from_primitive!(Integer, U64, u64);
define_value_from_primitive!(Integer, U128, u128);
define_value_from_primitive!(Integer, I8, i8);
define_value_from_primitive!(Integer, I16, i16);
define_value_from_primitive!(Integer, I32, i32);
define_value_from_primitive!(Integer, I64, i64);
define_value_from_primitive!(Integer, I128, i128);
define_value_from_primitive!(Float, F32, f32);
define_value_from_primitive!(Float, F64, f64);
impl<'a> From<&'a [u8]> for Value<'a> {
#[inline]
fn from(bytes: &'a [u8]) -> Self {
Self::Bytes(Cow::Borrowed(bytes))
}
}
impl<'a> From<Vec<u8>> for Value<'a> {
#[inline]
fn from(bytes: Vec<u8>) -> Self {
Self::Bytes(Cow::Owned(bytes))
}
}
impl<'a, const N: usize> From<&'a [u8; N]> for Value<'a> {
#[inline]
fn from(bytes: &'a [u8; N]) -> Self {
Self::Bytes(Cow::Borrowed(bytes))
}
}
impl<'a> From<&'a str> for Value<'a> {
#[inline]
fn from(string: &'a str) -> Self {
Self::String(Cow::Borrowed(string))
}
}
impl<'a> From<String> for Value<'a> {
#[inline]
fn from(string: String) -> Self {
Self::String(Cow::Owned(string))
}
}
impl<'a> From<Vec<Value<'a>>> for Value<'a> {
#[inline]
fn from(value: Vec<Value<'a>>) -> Self {
Self::Sequence(value)
}
}
impl<'a> From<Vec<(Value<'a>, Value<'a>)>> for Value<'a> {
#[inline]
fn from(value: Vec<(Value<'a>, Value<'a>)>) -> Self {
Self::Mappings(value)
}
}
impl<'a, A> FromIterator<A> for Value<'a>
where
A: Into<Value<'a>>,
{
#[inline]
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
Self::from(iter.into_iter().map(A::into).collect::<Vec<_>>())
}
}
impl<'a, K, V> FromIterator<(K, V)> for Value<'a>
where
K: Into<Value<'a>>,
V: Into<Value<'a>>,
{
#[inline]
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
Self::from(
iter.into_iter()
.map(|(k, v)| (k.into(), v.into()))
.collect::<Vec<_>>(),
)
}
}
pub struct ValueIter<'a>(SequenceIterState<'a>);
enum SequenceIterState<'a> {
Sequence(std::slice::Iter<'a, Value<'a>>),
Mappings(std::slice::Iter<'a, (Value<'a>, Value<'a>)>),
}
impl<'a> Iterator for ValueIter<'a> {
type Item = &'a Value<'a>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match &mut self.0 {
SequenceIterState::Sequence(sequence) => sequence.next(),
SequenceIterState::Mappings(mappings) => mappings.next().map(|(_k, v)| v),
}
}
}
impl<'a> ExactSizeIterator for ValueIter<'a> {
fn len(&self) -> usize {
match &self.0 {
SequenceIterState::Sequence(iter) => iter.len(),
SequenceIterState::Mappings(iter) => iter.len(),
}
}
}
impl<'a> DoubleEndedIterator for ValueIter<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
match &mut self.0 {
SequenceIterState::Sequence(iter) => iter.next_back(),
SequenceIterState::Mappings(iter) => iter.next_back().map(|(_k, v)| v),
}
}
}
#[test]
#[allow(clippy::cognitive_complexity)]
fn value_display_tests() {
assert_eq!(Value::None.to_string(), "None");
assert_eq!(Value::Unit.to_string(), "()");
assert_eq!(Value::Bool(false).to_string(), "false");
assert_eq!(Value::Bool(true).to_string(), "true");
assert_eq!(Value::from(1_u8).to_string(), "1");
assert_eq!(Value::from(1_u16).to_string(), "1");
assert_eq!(Value::from(1_u32).to_string(), "1");
assert_eq!(Value::from(1_u64).to_string(), "1");
assert_eq!(Value::from(1_u128).to_string(), "1");
assert_eq!(Value::from(1_i8).to_string(), "1");
assert_eq!(Value::from(1_i16).to_string(), "1");
assert_eq!(Value::from(1_i32).to_string(), "1");
assert_eq!(Value::from(1_i64).to_string(), "1");
assert_eq!(Value::from(1_i128).to_string(), "1");
assert_eq!(Value::from(1.1_f32).to_string(), "1.1");
assert_eq!(Value::from(1.1_f64).to_string(), "1.1");
assert_eq!(Value::from(b"\xFE\xED\xD0\xD0").to_string(), "0xfeedd0d0");
assert_eq!(
Value::from(b"\xFE\xED\xD0\xD0\xDE\xAD\xBE\xEF").to_string(),
"0xfeedd0d0_deadbeef"
);
assert_eq!(Value::from("hello world").to_string(), "hello world");
assert_eq!(
Value::from_sequence(Vec::<Value<'_>>::new()).to_string(),
"[]"
);
assert_eq!(
Value::from_sequence(vec![Value::None]).to_string(),
"[None]"
);
assert_eq!(
Value::from_sequence(vec![Value::None, Value::Unit]).to_string(),
"[None, ()]"
);
assert_eq!(
Value::from_mappings(Vec::<(Value<'_>, Value<'_>)>::new()).to_string(),
"{}"
);
assert_eq!(
Value::from_mappings(vec![(Value::from(0_u8), Value::None)]).to_string(),
"{0: None}"
);
assert_eq!(
Value::from_mappings(vec![
(Value::from(0_u8), Value::None),
(Value::from(1_u8), Value::Unit)
])
.to_string(),
"{0: None, 1: ()}"
);
}
#[test]
#[allow(clippy::manual_assert)] fn value_as_float_tests() {
approx::assert_relative_eq!(
Value::from(u8::MAX)
.as_float()
.expect("u8 conversion failed")
.as_f32()
.expect("f32 conversion failed"),
255_f32,
);
approx::assert_relative_eq!(
Value::from(u32::MAX)
.as_float()
.expect("u32 conversion failed")
.as_f64(),
4_294_967_295_f64,
);
assert!(Value::from(u32::MAX)
.as_float()
.expect("u32 conversion failed")
.as_f32()
.is_err());
approx::assert_relative_eq!(Value::from(0_f64).as_float().unwrap().as_f32().unwrap(), 0.);
}
#[test]
fn value_as_integer_tests() {
macro_rules! test_signed {
($primitive:ty, $signed_method:ident, $unsigned:ty, $unsigned_method:ident, $float:ty) => {
assert_eq!(
Value::from(<$primitive>::MAX)
.as_integer()
.expect("integer conversion failed")
.$signed_method()
.unwrap(),
<$primitive>::MAX,
);
assert_eq!(
Value::from(<$primitive>::MIN)
.as_integer()
.expect("integer conversion failed")
.$signed_method()
.unwrap(),
<$primitive>::MIN,
);
assert_eq!(
Value::from(<$primitive>::MAX)
.as_integer()
.expect("integer conversion failed")
.$unsigned_method()
.unwrap(),
<$unsigned>::try_from(<$primitive>::MAX).unwrap(),
);
assert_eq!(
Value::from(<$float>::from(<$primitive>::MAX))
.as_integer()
.expect("integer conversion failed")
.$signed_method()
.unwrap(),
<$primitive>::MAX,
);
assert_eq!(
Value::from(<$float>::from(<$primitive>::MIN))
.as_integer()
.expect("integer conversion failed")
.$signed_method()
.unwrap(),
<$primitive>::MIN,
);
assert_eq!(
Value::from(<$float>::from(<$primitive>::MAX))
.as_integer()
.expect("integer conversion failed")
.$unsigned_method()
.unwrap(),
<$unsigned>::try_from(<$primitive>::MAX).unwrap(),
);
};
}
test_signed!(i8, as_i8, u8, as_u8, f32);
test_signed!(i16, as_i16, u16, as_u16, f32);
test_signed!(i32, as_i32, u32, as_u32, f64);
macro_rules! test_unsigned {
($primitive:ty, $unsigned_method:ident, $signed:ty, $signed_method:ident, $float:ty) => {
assert_eq!(
Value::from(<$primitive>::MAX)
.as_integer()
.expect("integer conversion failed")
.$unsigned_method()
.unwrap(),
<$primitive>::MAX,
);
assert!(Value::from(<$primitive>::MAX)
.as_integer()
.expect("integer conversion failed")
.$signed_method()
.is_err());
assert_eq!(
Value::from(<$float>::from(<$primitive>::MAX))
.as_integer()
.expect("integer conversion failed")
.$unsigned_method()
.unwrap(),
<$primitive>::MAX,
);
assert!(Value::from(<$float>::from(<$primitive>::MAX))
.as_integer()
.expect("integer conversion failed")
.$signed_method()
.is_err());
};
}
test_unsigned!(u8, as_u8, i8, as_i8, f32);
test_unsigned!(u16, as_u16, i16, as_i16, f32);
test_unsigned!(u32, as_u32, i32, as_i32, f64);
}
struct Serializer;
impl serde::Serializer for Serializer {
type Error = ValueError;
type Ok = Value<'static>;
type SerializeMap = MappingsSerializer;
type SerializeSeq = SequenceSerializer;
type SerializeStruct = MappingsSerializer;
type SerializeStructVariant = StructVariantSerializer;
type SerializeTuple = SequenceSerializer;
type SerializeTupleStruct = SequenceSerializer;
type SerializeTupleVariant = TupleVariantSerializer;
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
Ok(Value::Bool(v))
}
fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
Ok(Value::Integer(Integer::from(v)))
}
fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
Ok(Value::Integer(Integer::from(v)))
}
fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
Ok(Value::Integer(Integer::from(v)))
}
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
Ok(Value::Integer(Integer::from(v)))
}
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
Ok(Value::Integer(Integer::from(v)))
}
fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
Ok(Value::Integer(Integer::from(v)))
}
fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
Ok(Value::Integer(Integer::from(v)))
}
fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
Ok(Value::Integer(Integer::from(v)))
}
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
Ok(Value::Integer(Integer::from(v)))
}
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
Ok(Value::Integer(Integer::from(v)))
}
fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
Ok(Value::Float(Float::from(v)))
}
fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
Ok(Value::Float(Float::from(v)))
}
fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
Ok(Value::Integer(Integer::from(u32::from(v))))
}
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
Ok(Value::String(Cow::Owned(v.to_string())))
}
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
Ok(Value::Bytes(Cow::Owned(v.to_vec())))
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Ok(Value::None)
}
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: Serialize + ?Sized,
{
value.serialize(Self)
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Ok(Value::Unit)
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
Ok(Value::Unit)
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
Ok(Value::String(Cow::Borrowed(variant)))
}
fn serialize_newtype_struct<T>(
self,
_name: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize + ?Sized,
{
value.serialize(Self)
}
fn serialize_newtype_variant<T>(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize + ?Sized,
{
Ok(Value::Mappings(vec![(
Value::String(Cow::Borrowed(variant)),
value.serialize(Self)?,
)]))
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Ok(SequenceSerializer(
len.map_or_else(Vec::new, Vec::with_capacity),
))
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
Ok(SequenceSerializer(Vec::with_capacity(len)))
}
fn serialize_tuple_struct(
self,
_name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
Ok(SequenceSerializer(Vec::with_capacity(len)))
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Ok(TupleVariantSerializer {
variant,
sequence: Vec::with_capacity(len),
})
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
Ok(MappingsSerializer(
len.map_or_else(Vec::new, Vec::with_capacity),
))
}
fn serialize_struct(
self,
_name: &'static str,
len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
Ok(MappingsSerializer(Vec::with_capacity(len)))
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
Ok(StructVariantSerializer {
variant,
mappings: Vec::with_capacity(len),
})
}
}
struct SequenceSerializer(Vec<Value<'static>>);
impl SerializeSeq for SequenceSerializer {
type Error = ValueError;
type Ok = Value<'static>;
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
self.0.push(value.serialize(Serializer)?);
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Value::Sequence(self.0))
}
}
impl SerializeTuple for SequenceSerializer {
type Error = ValueError;
type Ok = Value<'static>;
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
self.0.push(value.serialize(Serializer)?);
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Value::Sequence(self.0))
}
}
impl SerializeTupleStruct for SequenceSerializer {
type Error = ValueError;
type Ok = Value<'static>;
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
self.0.push(value.serialize(Serializer)?);
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Value::Sequence(self.0))
}
}
struct TupleVariantSerializer {
variant: &'static str,
sequence: Vec<Value<'static>>,
}
impl SerializeTupleVariant for TupleVariantSerializer {
type Error = ValueError;
type Ok = Value<'static>;
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
self.sequence.push(value.serialize(Serializer)?);
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Value::Mappings(vec![(
Value::String(Cow::Borrowed(self.variant)),
Value::Sequence(self.sequence),
)]))
}
}
struct MappingsSerializer(Vec<(Value<'static>, Value<'static>)>);
impl SerializeMap for MappingsSerializer {
type Error = ValueError;
type Ok = Value<'static>;
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
self.0.push((key.serialize(Serializer)?, Value::None));
Ok(())
}
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
self.0
.last_mut()
.expect("serialize_value called without serialize_key")
.1 = value.serialize(Serializer)?;
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Value::Mappings(self.0))
}
}
impl SerializeStruct for MappingsSerializer {
type Error = ValueError;
type Ok = Value<'static>;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
self.0.push((
Value::String(Cow::Borrowed(key)),
value.serialize(Serializer)?,
));
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Value::Mappings(self.0))
}
}
struct StructVariantSerializer {
variant: &'static str,
mappings: Vec<(Value<'static>, Value<'static>)>,
}
impl SerializeStructVariant for StructVariantSerializer {
type Error = ValueError;
type Ok = Value<'static>;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
self.mappings.push((
Value::String(Cow::Borrowed(key)),
value.serialize(Serializer)?,
));
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Value::Mappings(vec![(
Value::String(Cow::Borrowed(self.variant)),
Value::Mappings(self.mappings),
)]))
}
}
struct Deserializer<'de>(&'de Value<'de>);
impl<'de> serde::Deserializer<'de> for Deserializer<'de> {
type Error = ValueError;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match &self.0 {
Value::None => visitor.visit_none(),
Value::Unit => visitor.visit_unit(),
Value::Bool(value) => visitor.visit_bool(*value),
Value::Integer(integer) => match integer.0 {
InnerInteger::I8(value) => visitor.visit_i8(value),
InnerInteger::I16(value) => visitor.visit_i16(value),
InnerInteger::I32(value) => visitor.visit_i32(value),
InnerInteger::I64(value) => visitor.visit_i64(value),
InnerInteger::I128(value) => visitor.visit_i128(value),
InnerInteger::U8(value) => visitor.visit_u8(value),
InnerInteger::U16(value) => visitor.visit_u16(value),
InnerInteger::U32(value) => visitor.visit_u32(value),
InnerInteger::U64(value) => visitor.visit_u64(value),
InnerInteger::U128(value) => visitor.visit_u128(value),
},
Value::Float(float) => match float.0 {
InnerFloat::F64(value) => visitor.visit_f64(value),
InnerFloat::F32(value) => visitor.visit_f32(value),
},
Value::Bytes(bytes) => visitor.visit_bytes(bytes),
Value::String(str) => visitor.visit_str(str),
Value::Sequence(seq) => visitor.visit_seq(SequenceDeserializer(seq)),
Value::Mappings(mappings) => visitor.visit_map(MappingsDeserializer(mappings)),
}
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Bool(value) = &self.0 {
visitor.visit_bool(*value)
} else {
Err(ValueError::Expected {
kind: "bool",
value: self.0.to_static(),
})
}
}
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Integer(value) = &self.0 {
if let Ok(value) = value.as_i8() {
return visitor.visit_i8(value);
}
}
Err(ValueError::Expected {
kind: "i8",
value: self.0.to_static(),
})
}
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Integer(value) = &self.0 {
if let Ok(value) = value.as_i16() {
return visitor.visit_i16(value);
}
}
Err(ValueError::Expected {
kind: "i16",
value: self.0.to_static(),
})
}
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Integer(value) = &self.0 {
if let Ok(value) = value.as_i32() {
return visitor.visit_i32(value);
}
}
Err(ValueError::Expected {
kind: "i32",
value: self.0.to_static(),
})
}
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Integer(value) = &self.0 {
if let Ok(value) = value.as_i64() {
return visitor.visit_i64(value);
}
}
Err(ValueError::Expected {
kind: "i64",
value: self.0.to_static(),
})
}
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Integer(value) = &self.0 {
if let Ok(value) = value.as_i128() {
return visitor.visit_i128(value);
}
}
Err(ValueError::Expected {
kind: "i128",
value: self.0.to_static(),
})
}
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Integer(value) = &self.0 {
if let Ok(value) = value.as_u8() {
return visitor.visit_u8(value);
}
}
Err(ValueError::Expected {
kind: "u8",
value: self.0.to_static(),
})
}
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Integer(value) = &self.0 {
if let Ok(value) = value.as_u16() {
return visitor.visit_u16(value);
}
}
Err(ValueError::Expected {
kind: "u16",
value: self.0.to_static(),
})
}
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Integer(value) = &self.0 {
if let Ok(value) = value.as_u32() {
return visitor.visit_u32(value);
}
}
Err(ValueError::Expected {
kind: "u32",
value: self.0.to_static(),
})
}
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Integer(value) = &self.0 {
if let Ok(value) = value.as_u64() {
return visitor.visit_u64(value);
}
}
Err(ValueError::Expected {
kind: "u64",
value: self.0.to_static(),
})
}
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Integer(value) = &self.0 {
if let Ok(value) = value.as_u128() {
return visitor.visit_u128(value);
}
}
Err(ValueError::Expected {
kind: "u128",
value: self.0.to_static(),
})
}
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Float(value) = &self.0 {
if let Ok(value) = value.as_f32() {
return visitor.visit_f32(value);
}
}
Err(ValueError::Expected {
kind: "f32",
value: self.0.to_static(),
})
}
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Float(value) = &self.0 {
visitor.visit_f64(value.as_f64())
} else {
Err(ValueError::Expected {
kind: "f64",
value: self.0.to_static(),
})
}
}
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Integer(value) = &self.0 {
if let Ok(value) = value.as_u32() {
if let Ok(char) = char::try_from(value) {
return visitor.visit_char(char);
}
}
}
Err(ValueError::Expected {
kind: "char",
value: self.0.to_static(),
})
}
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::String(value) = &self.0 {
visitor.visit_borrowed_str(value)
} else {
Err(ValueError::Expected {
kind: "str",
value: self.0.to_static(),
})
}
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::String(value) = &self.0 {
visitor.visit_borrowed_str(value)
} else {
Err(ValueError::Expected {
kind: "String",
value: self.0.to_static(),
})
}
}
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Bytes(value) = &self.0 {
visitor.visit_borrowed_bytes(value)
} else {
Err(ValueError::Expected {
kind: "bytes",
value: self.0.to_static(),
})
}
}
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Bytes(value) = &self.0 {
visitor.visit_borrowed_bytes(value)
} else {
Err(ValueError::Expected {
kind: "byte buf",
value: self.0.to_static(),
})
}
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if matches!(&self.0, Value::None) {
visitor.visit_none()
} else {
visitor.visit_some(self)
}
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Unit = &self.0 {
visitor.visit_unit()
} else {
Err(ValueError::Expected {
kind: "()",
value: self.0.to_static(),
})
}
}
fn deserialize_unit_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Unit = &self.0 {
visitor.visit_unit()
} else {
Err(ValueError::Expected {
kind: "()",
value: self.0.to_static(),
})
}
}
fn deserialize_newtype_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_newtype_struct(self)
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Sequence(sequence) = &self.0 {
visitor.visit_seq(SequenceDeserializer(sequence))
} else {
Err(ValueError::Expected {
kind: "sequence",
value: self.0.to_static(),
})
}
}
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Sequence(sequence) = &self.0 {
visitor.visit_seq(SequenceDeserializer(sequence))
} else {
Err(ValueError::Expected {
kind: "tuple",
value: self.0.to_static(),
})
}
}
fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
_len: usize,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Sequence(sequence) = &self.0 {
visitor.visit_seq(SequenceDeserializer(sequence))
} else {
Err(ValueError::Expected {
kind: "tuple struct",
value: self.0.to_static(),
})
}
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Mappings(sequence) = &self.0 {
visitor.visit_map(MappingsDeserializer(sequence))
} else {
Err(ValueError::Expected {
kind: "map",
value: self.0.to_static(),
})
}
}
fn deserialize_struct<V>(
self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Mappings(sequence) = &self.0 {
visitor.visit_map(MappingsDeserializer(sequence))
} else {
Err(ValueError::Expected {
kind: "map",
value: self.0.to_static(),
})
}
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_enum(self)
}
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_str(visitor)
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_any(visitor)
}
}
impl<'de> EnumAccess<'de> for Deserializer<'de> {
type Error = ValueError;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
match &self.0 {
Value::Mappings(mapping) => {
if !mapping.is_empty() {
let variant = seed.deserialize(Deserializer(&mapping[0].0))?;
return Ok((variant, Deserializer(&mapping[0].1)));
}
}
Value::String(_) => {
let variant = seed.deserialize(Deserializer(self.0))?;
return Ok((variant, Deserializer(&Value::Unit)));
}
_ => {}
}
Err(ValueError::Expected {
kind: "enum variant",
value: self.0.to_static(),
})
}
}
impl<'de> VariantAccess<'de> for Deserializer<'de> {
type Error = ValueError;
fn unit_variant(self) -> Result<(), Self::Error> {
if matches!(self.0, Value::Unit) {
Ok(())
} else {
Err(ValueError::Expected {
kind: "unit",
value: self.0.to_static(),
})
}
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
seed.deserialize(self)
}
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Sequence(sequence) = &self.0 {
visitor.visit_seq(SequenceDeserializer(sequence))
} else {
Err(ValueError::Expected {
kind: "tuple variant",
value: self.0.to_static(),
})
}
}
fn struct_variant<V>(
self,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if let Value::Mappings(mappings) = &self.0 {
visitor.visit_map(MappingsDeserializer(mappings))
} else {
Err(ValueError::Expected {
kind: "struct variant",
value: self.0.to_static(),
})
}
}
}
struct SequenceDeserializer<'de>(&'de [Value<'de>]);
impl<'de> SeqAccess<'de> for SequenceDeserializer<'de> {
type Error = ValueError;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: serde::de::DeserializeSeed<'de>,
{
if self.0.is_empty() {
Ok(None)
} else {
let value = seed.deserialize(Deserializer(&self.0[0]))?;
self.0 = &self.0[1..];
Ok(Some(value))
}
}
fn size_hint(&self) -> Option<usize> {
Some(self.0.len())
}
}
struct MappingsDeserializer<'de>(&'de [(Value<'de>, Value<'de>)]);
impl<'de> MapAccess<'de> for MappingsDeserializer<'de> {
type Error = ValueError;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
where
K: serde::de::DeserializeSeed<'de>,
{
if self.0.is_empty() {
Ok(None)
} else {
let key = seed.deserialize(Deserializer(&self.0[0].0))?;
Ok(Some(key))
}
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
let value = seed.deserialize(Deserializer(&self.0[0].1))?;
self.0 = &self.0[1..];
Ok(value)
}
fn size_hint(&self) -> Option<usize> {
Some(self.0.len())
}
}
#[derive(Debug, PartialEq)]
pub enum ValueError {
Expected {
kind: &'static str,
value: Value<'static>,
},
Custom(String),
}
impl std::error::Error for ValueError {}
impl Display for ValueError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ValueError::Expected { kind, value } => write!(f, "expected {kind} but got {value}"),
ValueError::Custom(msg) => f.write_str(msg),
}
}
}
impl serde::de::Error for ValueError {
fn custom<T>(msg: T) -> Self
where
T: Display,
{
Self::Custom(msg.to_string())
}
}
impl serde::ser::Error for ValueError {
fn custom<T>(msg: T) -> Self
where
T: Display,
{
Self::Custom(msg.to_string())
}
}
#[test]
fn is_empty() {
for expected_empty in [
Value::None,
Value::Bytes(Cow::Borrowed(b"")),
Value::String(Cow::Borrowed("")),
Value::Sequence(vec![]),
Value::Mappings(vec![]),
] {
assert!(expected_empty.is_empty(), "{expected_empty} was not empty");
}
for expected_not_empty in [
Value::Unit,
Value::Bool(true),
Value::Integer(Integer::from(0)),
Value::Float(Float::from(0f32)),
Value::Bytes(Cow::Borrowed(b"a")),
Value::String(Cow::Borrowed("a")),
Value::Sequence(vec![Value::None]),
Value::Mappings(vec![(Value::None, Value::None)]),
] {
assert!(
!expected_not_empty.is_empty(),
"{expected_not_empty} was empty"
);
}
}
#[test]
fn as_bool() {
for expected_true in [
Value::Unit,
Value::Bool(true),
Value::Integer(Integer::from(1)),
Value::Float(Float::from(1f32)),
Value::Bytes(Cow::Borrowed(b"a")),
Value::String(Cow::Borrowed("a")),
Value::Sequence(vec![Value::None]),
Value::Mappings(vec![(Value::None, Value::None)]),
] {
assert!(expected_true.as_bool(), "{expected_true} was false");
}
for expected_false in [
Value::None,
Value::Bool(false),
Value::Integer(Integer::from(0)),
Value::Float(Float::from(0f32)),
Value::Bytes(Cow::Borrowed(b"")),
Value::String(Cow::Borrowed("")),
Value::Sequence(vec![]),
Value::Mappings(vec![]),
] {
assert!(!expected_false.as_bool(), "{expected_false} was true");
}
}
#[test]
fn as_integer() {
assert_eq!(
Value::from(1_i32).as_integer().unwrap().as_i32().unwrap(),
1
);
assert_eq!(
Value::from(1_f32).as_integer().unwrap().as_i32().unwrap(),
1
);
assert_eq!(Value::from(true).as_integer(), None);
}
#[test]
fn as_float() {
approx::assert_abs_diff_eq!(
Value::from(1_i32).as_float().unwrap().as_f32().unwrap(),
1_f32
);
approx::assert_abs_diff_eq!(
Value::from(1_f32).as_float().unwrap().as_f32().unwrap(),
1_f32
);
assert_eq!(Value::from(true).as_float(), None);
}
#[test]
fn as_str() {
assert_eq!(Value::from("asdf").as_str(), Some("asdf"));
assert_eq!(Value::from(b"asdf").as_str(), Some("asdf"));
assert_eq!(Value::from(false).as_str(), None);
}
#[test]
fn as_bytes() {
assert_eq!(Value::from(b"asdf").as_bytes(), Some(&b"asdf"[..]));
assert_eq!(Value::from("asdf").as_bytes(), Some(&b"asdf"[..]));
assert_eq!(Value::from(false).as_bytes(), None);
}
#[test]
fn values() {
assert_eq!(
Value::from_sequence([Value::Bool(true), Value::Bool(false)])
.values()
.collect::<Vec<_>>(),
&[&Value::Bool(true), &Value::Bool(false)]
);
assert_eq!(
Value::from_mappings([(0, Value::Bool(true)), (1, Value::Bool(false))])
.values()
.collect::<Vec<_>>(),
&[&Value::Bool(true), &Value::Bool(false)]
);
assert_eq!(Value::from(None).values().count(), 0);
}
#[test]
fn mappings() {
assert_eq!(
Value::from_sequence([Value::Bool(true), Value::Bool(false)])
.mappings()
.cloned()
.collect::<Vec<_>>(),
&[]
);
assert_eq!(
Value::from_mappings([(0, Value::Bool(true)), (1, Value::Bool(false))])
.mappings()
.collect::<Vec<_>>(),
&[
&(Value::from(0), Value::Bool(true)),
&(Value::from(1), Value::Bool(false))
]
);
assert!(Value::from(false).mappings().collect::<Vec<_>>().is_empty());
}
#[test]
fn into_static() {
for borrowed in [
Value::from(None),
Value::from(Some(Value::from(()))),
Value::from(true),
Value::from(1_i32),
Value::from(1_f32),
Value::from(&b"hi"[..]),
Value::from("hi"),
Value::from_sequence([1]),
Value::from_mappings([(1, 2)]),
] {
let cloned = borrowed.clone();
let s = borrowed.to_static();
assert_eq!(borrowed.to_static(), borrowed);
assert_eq!(borrowed, s.to_static());
assert_eq!(borrowed.into_static(), cloned);
assert_eq!(cloned, s.into_static());
}
}
#[test]
fn owned_deref() {
let mut owned_value = OwnedValue::from(&Value::from("hello".to_string()));
assert_eq!(owned_value.as_str(), Some("hello"));
let Value::String(Cow::Owned(str)) = &mut *owned_value else {
unreachable!()
};
str.push_str(", world");
assert_eq!(owned_value.as_str(), Some("hello, world"));
}
#[test]
fn owned_serialization() {
let owned_value = OwnedValue::from(Value::from(b"asdf".to_vec()));
let serialized = crate::to_vec(&owned_value).unwrap();
let deserialized_owned: OwnedValue = crate::from_slice(&serialized).unwrap();
assert_eq!(deserialized_owned, owned_value);
}