Lines
73.91 %
Functions
47.58 %
Branches
100 %
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};
/// A Pot-encoded value. This type can be used to deserialize to and from Pot
/// without knowing the original data structure.
#[derive(Debug, Clone)]
pub enum Value<'a> {
/// A value representing `None`.
None,
/// A value representing unit (`()`).
Unit,
/// A boolean value
Bool(bool),
/// An integer value.
Integer(Integer),
/// A floating point value.
Float(Float),
/// A value containing arbitrary bytes.
Bytes(Cow<'a, [u8]>),
/// A string value.
String(Cow<'a, str>),
/// A sequence of values.
Sequence(Vec<Self>),
/// A sequence of key-value mappings.
Mappings(Vec<(Self, Self)>),
}
impl<'a> Value<'a> {
/// Creates a `Value` from the given Serde-compatible type.
///
/// ```rust
/// # fn test() -> Result<(), pot::ValueError> {
/// use pot::Value;
/// use serde_derive::Serialize;
/// #[derive(Serialize, Debug)]
/// enum Example {
/// Hello,
/// World,
/// }
/// let original = vec![Example::Hello, Example::World];
/// let serialized = Value::from_serialize(&original)?;
/// assert_eq!(
/// serialized,
/// Value::Sequence(vec![
/// Value::from(String::from("Hello")),
/// Value::from(String::from("World"))
/// ])
/// );
/// # Ok(())
/// # }
/// ```
#[inline]
pub fn from_serialize<T: Serialize>(value: T) -> Result<Self, ValueError> {
value.serialize(Serializer)
/// Attempts to create an instance of `T` from this value.
/// use serde_derive::{Deserialize, Serialize};
/// #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
/// let deserialized: Vec<Example> = serialized.deserialize_as()?;
/// assert_eq!(deserialized, original);
pub fn deserialize_as<'de, T: Deserialize<'de>>(&'de self) -> Result<T, ValueError> {
T::deserialize(Deserializer(self))
/// Returns a new value from an iterator of items that can be converted into a value.
/// # use pot::Value;
/// let mappings = Value::from_sequence(Vec::<String>::new());
/// assert!(matches!(mappings, Value::Sequence(_)));
pub fn from_sequence<IntoIter: IntoIterator<Item = T>, T: Into<Self>>(
sequence: IntoIter,
) -> Self {
Self::from_iter(sequence)
/// Returns a new value from an iterator of 2-element tuples representing key-value pairs.
/// # use std::collections::HashMap;
/// let mappings = Value::from_mappings(HashMap::<String, u32>::new());
/// assert!(matches!(mappings, Value::Mappings(_)));
pub fn from_mappings<IntoIter: IntoIterator<Item = (K, V)>, K: Into<Self>, V: Into<Self>>(
mappings: IntoIter,
Self::from_iter(mappings)
/// Returns `true` if the value contained is considered empty.
/// // Value::None is always empty.
/// assert_eq!(Value::None.is_empty(), true);
/// // All primitive values, including Unit, are always not empty, even if they contain the value 0.
/// assert_eq!(Value::Unit.is_empty(), false);
/// assert_eq!(Value::from(false).is_empty(), false);
/// assert_eq!(Value::from(0_u8).is_empty(), false);
/// assert_eq!(Value::from(0_f32).is_empty(), false);
/// // For all other types, having a length of 0 will result in is_empty returning true.
/// assert_eq!(Value::from(Vec::<u8>::new()).is_empty(), true);
/// assert_eq!(Value::from(b"").is_empty(), true);
/// assert_eq!(Value::from(vec![0_u8]).is_empty(), false);
/// assert_eq!(Value::from("").is_empty(), true);
/// assert_eq!(Value::from("hi").is_empty(), false);
/// assert_eq!(Value::Sequence(Vec::new()).is_empty(), true);
/// assert_eq!(Value::from(vec![Value::None]).is_empty(), false);
/// assert_eq!(Value::Mappings(Vec::new()).is_empty(), true);
/// Value::from(vec![(Value::None, Value::None)]).is_empty(),
/// false
#[must_use]
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(),
/// Returns the value as a `bool`.
/// // Value::None is always false.
/// assert_eq!(Value::None.as_bool(), false);
/// // Value::Unit is always true.
/// assert_eq!(Value::Unit.as_bool(), true);
/// // Value::Bool will return the contained value
/// assert_eq!(Value::from(false).as_bool(), false);
/// assert_eq!(Value::from(true).as_bool(), true);
/// // All primitive values return true if the value is non-zero.
/// assert_eq!(Value::from(0_u8).as_bool(), false);
/// assert_eq!(Value::from(1_u8).as_bool(), true);
/// assert_eq!(Value::from(0_f32).as_bool(), false);
/// assert_eq!(Value::from(1_f32).as_bool(), true);
/// // For all other types, as_bool() returns the result of `!is_empty()`.
/// assert_eq!(Value::from(Vec::<u8>::new()).as_bool(), false);
/// assert_eq!(Value::from(b"").as_bool(), false);
/// assert_eq!(Value::from(vec![0_u8]).as_bool(), true);
/// assert_eq!(Value::from("").as_bool(), false);
/// assert_eq!(Value::from("hi").as_bool(), true);
/// assert_eq!(Value::Sequence(Vec::new()).as_bool(), false);
/// assert_eq!(Value::from(vec![Value::None]).as_bool(), true);
/// assert_eq!(Value::Mappings(Vec::new()).as_bool(), false);
/// Value::from(vec![(Value::None, Value::None)]).as_bool(),
/// true
pub fn as_bool(&self) -> bool {
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(),
/// Returns the value as an [`Integer`]. Returns `None` if the value is not a
/// [`Self::Float`] or [`Self::Integer`]. Also returns `None` if the value is
/// a float, but cannot be losslessly converted to an integer.
pub fn as_integer(&self) -> Option<Integer> {
Value::Integer(value) => Some(*value),
Value::Float(value) => value.as_integer().ok(),
_ => None,
/// Returns the value as an [`Float`]. Returns `None` if the value is not a
/// an integer, but cannot be losslessly converted to a float.
pub fn as_float(&self) -> Option<Float> {
Value::Integer(value) => value.as_float().ok(),
Value::Float(value) => Some(*value),
/// Returns the value as a string, or `None` if the value is not representable
/// by a string. This will only return a value with variants
/// [`Self::String`] and [`Self::Bytes`]. Bytes will only be returned if the
/// contained bytes can be safely interpretted as UTF-8.
pub fn as_str(&self) -> Option<&str> {
Self::Bytes(bytes) => std::str::from_utf8(bytes).ok(),
Self::String(string) => Some(string),
/// Returns the value as bytes, or `None` if the value is not stored as a
/// representation of bytes. This will only return a value with variants
/// [`Self::String`] and [`Self::Bytes`].
pub fn as_bytes(&self) -> Option<&[u8]> {
Self::Bytes(bytes) => Some(bytes),
Self::String(string) => Some(string.as_bytes()),
/// Returns an iterator that iterates over all values contained inside of
/// this value. Returns an empty iterator if not a [`Self::Sequence`] or
/// [`Self::Mappings`]. If a [`Self::Mappings`], only the value portion of
/// the mapping is returned.
pub fn values(&self) -> ValueIter<'_> {
Self::Sequence(sequence) => ValueIter(SequenceIterState::Sequence(sequence.iter())),
Self::Mappings(mappings) => ValueIter(SequenceIterState::Mappings(mappings.iter())),
_ => ValueIter(SequenceIterState::Sequence([].iter())),
/// Returns an iterator that iterates over all mappings contained inside of
/// [`Self::Mappings`]. If a [`Self::Sequence`], the key will always be
/// `Self::None`.
pub fn mappings(&self) -> std::slice::Iter<'_, (Self, Self)> {
Self::Mappings(mappings) => mappings.iter(),
_ => [].iter(),
/// Converts `self` to a `'static` lifetime by cloning any borrowed data.
pub fn into_static(self) -> Value<'static> {
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(),
),
/// Converts `self` to a `'static` lifetime by cloning all data.
pub fn to_static(&self) -> Value<'static> {
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::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()),
.iter()
.map(|(k, v)| (k.to_static(), v.to_static()))
impl<'a, 'b> PartialEq<Value<'b>> for Value<'a> {
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 {
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() {
Display::fmt(key, f)?;
f.write_str(": ")?;
f.write_char('}')
impl<'a> Serialize for Value<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
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> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
D: serde::Deserializer<'de>,
deserializer.deserialize_any(ValueVisitor::default())
/// A <code>[Value]<'static></code> wrapper that supports
/// [`DeserializeOwned`](serde::de::DeserializeOwned).
/// Because `Value<'a>` can borrow strings and bytes during deserialization,
/// `Value<'static>` can't be used when `DeserializeOwned` is needed.
/// [`OwnedValue`] implements [`Deserialize`] by first deserializing a
/// `Value<'a>` and then using [`Value::into_static`] to convert borrowed data
/// to owned data.
#[derive(Debug, Clone, PartialEq)]
pub struct OwnedValue(pub Value<'static>);
impl Deref for OwnedValue {
type Target = Value<'static>;
fn deref(&self) -> &Self::Target {
&self.0
impl DerefMut for OwnedValue {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
impl Serialize for OwnedValue {
self.0.serialize(serializer)
impl<'de> Deserialize<'de> for OwnedValue {
deserializer
.deserialize_any(ValueVisitor::default())
.map(|value| Self(value.into_static()))
impl<'a> From<Value<'a>> for OwnedValue {
fn from(value: Value<'a>) -> Self {
Self(value.into_static())
impl<'a> From<&'a Value<'a>> for OwnedValue {
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")
fn visit_none<E>(self) -> Result<Self::Value, E>
E: serde::de::Error,
Ok(Value::None)
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
Ok(Value::Bool(v))
fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
Ok(Value::Integer(Integer::from(v)))
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
Ok(Value::Float(Float::from(v)))
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
Ok(Value::String(Cow::Owned(v.to_string())))
fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E>
Ok(Value::String(Cow::Borrowed(v)))
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
Ok(Value::String(Cow::Owned(v)))
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
Ok(Value::Bytes(Cow::Owned(v.to_vec())))
fn visit_borrowed_bytes<E>(self, v: &'a [u8]) -> Result<Self::Value, E>
Ok(Value::Bytes(Cow::Borrowed(v)))
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
Ok(Value::Bytes(Cow::Owned(v)))
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
deserializer.deserialize_any(Self::default())
fn visit_unit<E>(self) -> Result<Self::Value, E>
Ok(Value::Unit)
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
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))
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
A: serde::de::MapAccess<'de>,
let mut values = if let Some(hint) = map.size_hint() {
while let Some(value) = map.next_entry()? {
Ok(Value::Mappings(values))
impl<'a> From<Option<Value<'a>>> for Value<'a> {
fn from(value: Option<Value<'a>>) -> Self {
if let Some(value) = value {
Value::None
impl<'a> From<()> for Value<'a> {
fn from(_: ()) -> Self {
Value::Unit
impl<'a> From<bool> for Value<'a> {
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> {
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> {
fn from(bytes: &'a [u8]) -> Self {
Self::Bytes(Cow::Borrowed(bytes))
impl<'a> From<Vec<u8>> for Value<'a> {
fn from(bytes: Vec<u8>) -> Self {
Self::Bytes(Cow::Owned(bytes))
impl<'a, const N: usize> From<&'a [u8; N]> for Value<'a> {
fn from(bytes: &'a [u8; N]) -> Self {
impl<'a> From<&'a str> for Value<'a> {
fn from(string: &'a str) -> Self {
Self::String(Cow::Borrowed(string))
impl<'a> From<String> for Value<'a> {
fn from(string: String) -> Self {
Self::String(Cow::Owned(string))
impl<'a> From<Vec<Value<'a>>> for Value<'a> {
fn from(value: Vec<Value<'a>>) -> Self {
Self::Sequence(value)
impl<'a> From<Vec<(Value<'a>, Value<'a>)>> for Value<'a> {
fn from(value: Vec<(Value<'a>, Value<'a>)>) -> Self {
Self::Mappings(value)
impl<'a, A> FromIterator<A> for Value<'a>
A: Into<Value<'a>>,
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>
K: Into<Value<'a>>,
V: Into<Value<'a>>,
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<_>>(),
)
/// An iterator over values contained within a [`Value`].
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>;
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> {
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() {
// Specials
assert_eq!(Value::None.to_string(), "None");
assert_eq!(Value::Unit.to_string(), "()");
// Boolean
assert_eq!(Value::Bool(false).to_string(), "false");
assert_eq!(Value::Bool(true).to_string(), "true");
// Integer
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");
// Float
assert_eq!(Value::from(1.1_f32).to_string(), "1.1");
assert_eq!(Value::from(1.1_f64).to_string(), "1.1");
// Bytes
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"
);
// String
assert_eq!(Value::from("hello world").to_string(), "hello world");
// Sequence
Value::from_sequence(Vec::<Value<'_>>::new()).to_string(),
"[]"
Value::from_sequence(vec![Value::None]).to_string(),
"[None]"
Value::from_sequence(vec![Value::None, Value::Unit]).to_string(),
"[None, ()]"
// Mappings
Value::from_mappings(Vec::<(Value<'_>, Value<'_>)>::new()).to_string(),
"{}"
Value::from_mappings(vec![(Value::from(0_u8), Value::None)]).to_string(),
"{0: None}"
Value::from_mappings(vec![
(Value::from(0_u8), Value::None),
(Value::from(1_u8), Value::Unit)
])
.to_string(),
"{0: None, 1: ()}"
#[allow(clippy::manual_assert)] // approx::assert_relative_eq false positive
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,
Value::from(u32::MAX)
.expect("u32 conversion failed")
.as_f64(),
4_294_967_295_f64,
assert!(Value::from(u32::MAX)
.is_err());
approx::assert_relative_eq!(Value::from(0_f64).as_float().unwrap().as_f32().unwrap(), 0.);
fn value_as_integer_tests() {
macro_rules! test_signed {
($primitive:ty, $signed_method:ident, $unsigned:ty, $unsigned_method:ident, $float:ty) => {
Value::from(<$primitive>::MAX)
.as_integer()
.expect("integer conversion failed")
.$signed_method()
.unwrap(),
<$primitive>::MAX,
Value::from(<$primitive>::MIN)
<$primitive>::MIN,
.$unsigned_method()
<$unsigned>::try_from(<$primitive>::MAX).unwrap(),
Value::from(<$float>::from(<$primitive>::MAX))
Value::from(<$float>::from(<$primitive>::MIN))
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!(Value::from(<$primitive>::MAX)
assert!(Value::from(<$float>::from(<$primitive>::MAX))
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> {
fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
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> {
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
T: Serialize + ?Sized,
value.serialize(Self)
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
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>(
value: &T,
) -> Result<Self::Ok, Self::Error>
fn serialize_newtype_variant<T>(
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(
len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
fn serialize_tuple_variant(
) -> 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(
fn serialize_struct(
) -> Result<Self::SerializeStruct, Self::Error> {
Ok(MappingsSerializer(Vec::with_capacity(len)))
fn serialize_struct_variant(
) -> Result<Self::SerializeStructVariant, Self::Error> {
Ok(StructVariantSerializer {
mappings: Vec::with_capacity(len),
struct SequenceSerializer(Vec<Value<'static>>);
impl SerializeSeq for SequenceSerializer {
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
self.0.push(value.serialize(Serializer)?);
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Value::Sequence(self.0))
impl SerializeTuple for SequenceSerializer {
impl SerializeTupleStruct for SequenceSerializer {
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
struct TupleVariantSerializer {
sequence: Vec<Value<'static>>,
impl SerializeTupleVariant for TupleVariantSerializer {
self.sequence.push(value.serialize(Serializer)?);
Value::String(Cow::Borrowed(self.variant)),
Value::Sequence(self.sequence),
struct MappingsSerializer(Vec<(Value<'static>, Value<'static>)>);
impl SerializeMap for MappingsSerializer {
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
self.0.push((key.serialize(Serializer)?, Value::None));
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
self.0
.last_mut()
.expect("serialize_value called without serialize_key")
.1 = value.serialize(Serializer)?;
Ok(Value::Mappings(self.0))
impl SerializeStruct for MappingsSerializer {
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
self.0.push((
Value::String(Cow::Borrowed(key)),
value.serialize(Serializer)?,
));
struct StructVariantSerializer {
mappings: Vec<(Value<'static>, Value<'static>)>,
impl SerializeStructVariant for StructVariantSerializer {
self.mappings.push((
Value::Mappings(self.mappings),
struct Deserializer<'de>(&'de Value<'de>);
impl<'de> serde::Deserializer<'de> for Deserializer<'de> {
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
V: Visitor<'de>,
Value::None => visitor.visit_none(),
Value::Unit => visitor.visit_unit(),
Value::Bool(value) => visitor.visit_bool(*value),
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>
if let Value::Bool(value) = &self.0 {
visitor.visit_bool(*value)
Err(ValueError::Expected {
kind: "bool",
value: self.0.to_static(),
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Value::Integer(value) = &self.0 {
if let Ok(value) = value.as_i8() {
return visitor.visit_i8(value);
kind: "i8",
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Ok(value) = value.as_i16() {
return visitor.visit_i16(value);
kind: "i16",
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Ok(value) = value.as_i32() {
return visitor.visit_i32(value);
kind: "i32",
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Ok(value) = value.as_i64() {
return visitor.visit_i64(value);
kind: "i64",
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Ok(value) = value.as_i128() {
return visitor.visit_i128(value);
kind: "i128",
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Ok(value) = value.as_u8() {
return visitor.visit_u8(value);
kind: "u8",
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Ok(value) = value.as_u16() {
return visitor.visit_u16(value);
kind: "u16",
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Ok(value) = value.as_u32() {
return visitor.visit_u32(value);
kind: "u32",
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Ok(value) = value.as_u64() {
return visitor.visit_u64(value);
kind: "u64",
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Ok(value) = value.as_u128() {
return visitor.visit_u128(value);
kind: "u128",
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Value::Float(value) = &self.0 {
if let Ok(value) = value.as_f32() {
return visitor.visit_f32(value);
kind: "f32",
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
visitor.visit_f64(value.as_f64())
kind: "f64",
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Ok(char) = char::try_from(value) {
return visitor.visit_char(char);
kind: "char",
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Value::String(value) = &self.0 {
visitor.visit_borrowed_str(value)
kind: "str",
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
kind: "String",
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Value::Bytes(value) = &self.0 {
visitor.visit_borrowed_bytes(value)
kind: "bytes",
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
kind: "byte buf",
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if matches!(&self.0, Value::None) {
visitor.visit_none()
visitor.visit_some(self)
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Value::Unit = &self.0 {
visitor.visit_unit()
kind: "()",
fn deserialize_unit_struct<V>(
visitor: V,
) -> Result<V::Value, Self::Error>
fn deserialize_newtype_struct<V>(
visitor.visit_newtype_struct(self)
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Value::Sequence(sequence) = &self.0 {
visitor.visit_seq(SequenceDeserializer(sequence))
kind: "sequence",
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
kind: "tuple",
fn deserialize_tuple_struct<V>(
_len: usize,
kind: "tuple struct",
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
if let Value::Mappings(sequence) = &self.0 {
visitor.visit_map(MappingsDeserializer(sequence))
kind: "map",
fn deserialize_struct<V>(
_fields: &'static [&'static str],
fn deserialize_enum<V>(
_variants: &'static [&'static str],
visitor.visit_enum(self)
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
self.deserialize_str(visitor)
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
self.deserialize_any(visitor)
impl<'de> EnumAccess<'de> for Deserializer<'de> {
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
V: serde::de::DeserializeSeed<'de>,
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)));
_ => {}
kind: "enum variant",
impl<'de> VariantAccess<'de> for Deserializer<'de> {
fn unit_variant(self) -> Result<(), Self::Error> {
if matches!(self.0, Value::Unit) {
kind: "unit",
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
T: serde::de::DeserializeSeed<'de>,
seed.deserialize(self)
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
kind: "tuple variant",
fn struct_variant<V>(
if let Value::Mappings(mappings) = &self.0 {
visitor.visit_map(MappingsDeserializer(mappings))
kind: "struct variant",
struct SequenceDeserializer<'de>(&'de [Value<'de>]);
impl<'de> SeqAccess<'de> for SequenceDeserializer<'de> {
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
if self.0.is_empty() {
Ok(None)
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> {
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
K: serde::de::DeserializeSeed<'de>,
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>
let value = seed.deserialize(Deserializer(&self.0[0].1))?;
Ok(value)
/// An error from deserializing a type using [`Value::deserialize_as`].
#[derive(Debug, PartialEq)]
pub enum ValueError {
/// A kind of data was expected, but the [`Value`] cannot be interpreted as
/// that kind.
Expected {
/// The kind of data expected.
kind: &'static str,
/// The value that was encountered.
value: Value<'static>,
/// A custom deserialization error. These errors originate outside of Pot.
Custom(String),
impl std::error::Error for ValueError {}
impl Display for ValueError {
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
T: Display,
Self::Custom(msg.to_string())
impl serde::ser::Error for ValueError {
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"
fn as_bool() {
for expected_true in [
Value::Integer(Integer::from(1)),
Value::Float(Float::from(1f32)),
assert!(expected_true.as_bool(), "{expected_true} was false");
for expected_false in [
Value::Bool(false),
assert!(!expected_false.as_bool(), "{expected_false} was true");
fn as_integer() {
Value::from(1_i32).as_integer().unwrap().as_i32().unwrap(),
1
Value::from(1_f32).as_integer().unwrap().as_i32().unwrap(),
assert_eq!(Value::from(true).as_integer(), None);
fn as_float() {
approx::assert_abs_diff_eq!(
Value::from(1_i32).as_float().unwrap().as_f32().unwrap(),
1_f32
Value::from(1_f32).as_float().unwrap().as_f32().unwrap(),
assert_eq!(Value::from(true).as_float(), None);
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);
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);
fn values() {
Value::from_sequence([Value::Bool(true), Value::Bool(false)])
.values()
&[&Value::Bool(true), &Value::Bool(false)]
Value::from_mappings([(0, Value::Bool(true)), (1, Value::Bool(false))])
assert_eq!(Value::from(None).values().count(), 0);
fn mappings() {
.mappings()
.cloned()
&[]
&[
&(Value::from(0), Value::Bool(true)),
&(Value::from(1), Value::Bool(false))
]
assert!(Value::from(false).mappings().collect::<Vec<_>>().is_empty());
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);
// The first pass had borrowed strings/bytes. The static version has
// owned values, so these invocations take a slightly different path.
assert_eq!(borrowed, s.to_static());
assert_eq!(borrowed.into_static(), cloned);
assert_eq!(cloned, s.into_static());
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"));
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);