mod deserialize;
mod deserializer;
mod serialize;
use bitvec::{order::Lsb0, vec::BitVec};
use serde::Deserialize;
use std::convert::From;
use std::fmt::Debug;
#[derive(Debug, Clone, PartialEq)]
pub struct Value<T> {
pub value: ValueDef<T>,
pub context: T,
}
macro_rules! value_prim_method {
($name:ident $variant:ident) => {
#[doc = concat!("Create a new `", stringify!($name), "` value without additional context")]
pub fn $name(val: $name) -> Value<()> {
Value { value: ValueDef::Primitive(Primitive::$variant(val)), context: () }
}
}
}
impl Value<()> {
pub fn named_composite(values: Vec<(String, Value<()>)>) -> Value<()> {
Value { value: ValueDef::Composite(Composite::Named(values)), context: () }
}
pub fn unnamed_composite(values: Vec<Value<()>>) -> Value<()> {
Value { value: ValueDef::Composite(Composite::Unnamed(values)), context: () }
}
pub fn variant(name: String, values: Composite<()>) -> Value<()> {
Value { value: ValueDef::Variant(Variant { name, values }), context: () }
}
pub fn bit_sequence(bitseq: BitSequence) -> Value<()> {
Value { value: ValueDef::BitSequence(bitseq), context: () }
}
pub fn primitive(primitive: Primitive) -> Value<()> {
Value { value: ValueDef::Primitive(primitive), context: () }
}
pub fn str(val: String) -> Value<()> {
Value { value: ValueDef::Primitive(Primitive::Str(val)), context: () }
}
value_prim_method!(bool Bool);
value_prim_method!(char Char);
value_prim_method!(u8 U8);
value_prim_method!(u16 U16);
value_prim_method!(u32 U32);
value_prim_method!(u64 U64);
value_prim_method!(u128 U128);
value_prim_method!(i8 I8);
value_prim_method!(i16 I16);
value_prim_method!(i32 I32);
value_prim_method!(i64 I64);
value_prim_method!(i128 I128);
}
impl<T> Value<T> {
pub fn with_context(value: ValueDef<T>, context: T) -> Value<T> {
Value { value, context }
}
pub fn without_context(self) -> Value<()> {
self.map_context(|_| ())
}
pub fn map_context<F, U>(self, mut f: F) -> Value<U>
where
F: Clone + FnMut(T) -> U,
{
Value { context: f(self.context), value: self.value.map_context(f) }
}
}
#[derive(Clone, PartialEq)]
pub enum ValueDef<T> {
Composite(Composite<T>),
Variant(Variant<T>),
BitSequence(BitSequence),
Primitive(Primitive),
}
impl<T> ValueDef<T> {
pub fn map_context<F, U>(self, f: F) -> ValueDef<U>
where
F: Clone + FnMut(T) -> U,
{
match self {
ValueDef::Composite(val) => ValueDef::Composite(val.map_context(f)),
ValueDef::Variant(val) => ValueDef::Variant(val.map_context(f)),
ValueDef::BitSequence(val) => ValueDef::BitSequence(val),
ValueDef::Primitive(val) => ValueDef::Primitive(val),
}
}
}
impl<T: Debug> Debug for ValueDef<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Composite(val) => Debug::fmt(val, f),
Self::Variant(val) => Debug::fmt(val, f),
Self::Primitive(val) => Debug::fmt(val, f),
Self::BitSequence(val) => Debug::fmt(val, f),
}
}
}
#[derive(Clone, PartialEq)]
pub enum Composite<T> {
Named(Vec<(String, Value<T>)>),
Unnamed(Vec<Value<T>>),
}
impl<T> Composite<T> {
pub fn len(&self) -> usize {
match self {
Composite::Named(values) => values.len(),
Composite::Unnamed(values) => values.len(),
}
}
pub fn is_empty(&self) -> bool {
match self {
Composite::Named(values) => values.is_empty(),
Composite::Unnamed(values) => values.is_empty(),
}
}
pub fn map_context<F, U>(self, f: F) -> Composite<U>
where
F: Clone + FnMut(T) -> U,
{
match self {
Composite::Named(values) => {
let vals = values.into_iter().map(move |(k, v)| (k, v.map_context(f.clone()))).collect();
Composite::Named(vals)
}
Composite::Unnamed(values) => {
let vals = values.into_iter().map(move |v| v.map_context(f.clone())).collect();
Composite::Unnamed(vals)
}
}
}
}
impl<T: Debug> Debug for Composite<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Composite::Named(fields) => {
let mut struc = f.debug_struct("");
for (name, val) in fields {
struc.field(name, val);
}
struc.finish()
}
Composite::Unnamed(fields) => {
let mut struc = f.debug_tuple("");
for val in fields {
struc.field(val);
}
struc.finish()
}
}
}
}
impl<T> From<Composite<T>> for ValueDef<T> {
fn from(val: Composite<T>) -> Self {
ValueDef::Composite(val)
}
}
#[derive(Clone, PartialEq)]
pub struct Variant<T> {
pub name: String,
pub values: Composite<T>,
}
impl<T> Variant<T> {
pub fn map_context<F, U>(self, f: F) -> Variant<U>
where
F: Clone + FnMut(T) -> U,
{
Variant { name: self.name, values: self.values.map_context(f) }
}
}
impl<T: Debug> Debug for Variant<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.name)?;
f.write_str(" ")?;
Debug::fmt(&self.values, f)
}
}
impl<T> From<Variant<T>> for ValueDef<T> {
fn from(val: Variant<T>) -> Self {
ValueDef::Variant(val)
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Primitive {
Bool(bool),
Char(char),
Str(String),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
U128(u128),
U256([u8; 32]),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
I128(i128),
I256([u8; 32]),
}
impl<T> From<Primitive> for ValueDef<T> {
fn from(val: Primitive) -> Self {
ValueDef::Primitive(val)
}
}
pub type BitSequence = BitVec<Lsb0, u8>;
pub use deserializer::Error as DeserializeError;
pub fn from_value<'de, Ctx, T: Deserialize<'de>>(value: Value<Ctx>) -> Result<T, DeserializeError> {
T::deserialize(value)
}