use crate::prelude::*;
use either::Either;
pub use scale_bits::Bits as BitSequence;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Value<T = ()> {
pub value: ValueDef<T>,
pub context: T,
}
impl Value<()> {
pub fn named_composite<S, Vals>(vals: Vals) -> Self
where
S: Into<String>,
Vals: IntoIterator<Item = (S, Value<()>)>,
{
Value { value: ValueDef::Composite(Composite::named(vals)), context: () }
}
pub fn unnamed_composite<Vals>(vals: Vals) -> Self
where
Vals: IntoIterator<Item = Value<()>>,
{
Value { value: ValueDef::Composite(Composite::unnamed(vals)), context: () }
}
pub fn variant<S: Into<String>>(name: S, values: Composite<()>) -> Value<()> {
Value { value: ValueDef::Variant(Variant { name: name.into(), values }), context: () }
}
pub fn named_variant<S, F, Vals>(name: S, fields: Vals) -> Value<()>
where
S: Into<String>,
F: Into<String>,
Vals: IntoIterator<Item = (F, Value<()>)>,
{
Value { value: ValueDef::Variant(Variant::named_fields(name, fields)), context: () }
}
pub fn unnamed_variant<S, Vals>(name: S, fields: Vals) -> Value<()>
where
S: Into<String>,
Vals: IntoIterator<Item = Value<()>>,
{
Value { value: ValueDef::Variant(Variant::unnamed_fields(name, fields)), context: () }
}
pub fn bit_sequence(bits: BitSequence) -> Value<()> {
Value { value: ValueDef::BitSequence(bits), context: () }
}
pub fn primitive(primitive: Primitive) -> Value<()> {
Value { value: ValueDef::Primitive(primitive), context: () }
}
pub fn string<S: Into<String>>(val: S) -> Value<()> {
Value { value: ValueDef::Primitive(Primitive::String(val.into())), context: () }
}
pub fn bool(val: bool) -> Value<()> {
Value { value: ValueDef::Primitive(Primitive::Bool(val)), context: () }
}
pub fn char(val: char) -> Value<()> {
Value { value: ValueDef::Primitive(Primitive::Char(val)), context: () }
}
pub fn u128(val: u128) -> Value<()> {
Value { value: ValueDef::Primitive(Primitive::u128(val)), context: () }
}
pub fn i128(val: i128) -> Value<()> {
Value { value: ValueDef::Primitive(Primitive::i128(val)), context: () }
}
pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Value<()> {
let vals: Vec<_> = bytes.as_ref().iter().map(|&b| Value::u128(b as u128)).collect();
Value::unnamed_composite(vals)
}
}
impl Value<()> {
pub fn without_context(value: ValueDef<()>) -> Value<()> {
Value { value, context: () }
}
}
impl<T> Value<T> {
pub fn with_context(value: ValueDef<T>, context: T) -> Value<T> {
Value { value, context }
}
pub fn remove_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) }
}
pub fn as_bool(&self) -> Option<bool> {
match &self.value {
ValueDef::Primitive(p) => p.as_bool(),
_ => None,
}
}
pub fn as_char(&self) -> Option<char> {
match &self.value {
ValueDef::Primitive(p) => p.as_char(),
_ => None,
}
}
pub fn as_u128(&self) -> Option<u128> {
match &self.value {
ValueDef::Primitive(p) => p.as_u128(),
_ => None,
}
}
pub fn as_i128(&self) -> Option<i128> {
match &self.value {
ValueDef::Primitive(p) => p.as_i128(),
_ => None,
}
}
pub fn as_str(&self) -> Option<&str> {
match &self.value {
ValueDef::Primitive(p) => p.as_str(),
_ => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
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> From<BitSequence> for ValueDef<T> {
fn from(val: BitSequence) -> Self {
ValueDef::BitSequence(val)
}
}
impl From<BitSequence> for Value<()> {
fn from(val: BitSequence) -> Self {
Value::without_context(val.into())
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Composite<T> {
Named(Vec<(String, Value<T>)>),
Unnamed(Vec<Value<T>>),
}
impl<T> Composite<T> {
pub fn named<S: Into<String>, Vals: IntoIterator<Item = (S, Value<T>)>>(vals: Vals) -> Self {
Composite::Named(vals.into_iter().map(|(n, v)| (n.into(), v)).collect())
}
pub fn unnamed<Vals: IntoIterator<Item = Value<T>>>(vals: Vals) -> Self {
Composite::Unnamed(vals.into_iter().collect())
}
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 values(&self) -> impl ExactSizeIterator<Item = &Value<T>> {
match self {
Composite::Named(values) => Either::Left(values.iter().map(|(_k, v)| v)),
Composite::Unnamed(values) => Either::Right(values.iter()),
}
}
pub fn into_values(self) -> impl ExactSizeIterator<Item = Value<T>> {
match self {
Composite::Named(values) => Either::Left(values.into_iter().map(|(_k, v)| v)),
Composite::Unnamed(values) => Either::Right(values.into_iter()),
}
}
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<V: Into<Value<()>>> From<Vec<V>> for Composite<()> {
fn from(vals: Vec<V>) -> Self {
let vals = vals.into_iter().map(|v| v.into()).collect();
Composite::Unnamed(vals)
}
}
impl<V: Into<Value<()>>> From<Vec<V>> for ValueDef<()> {
fn from(vals: Vec<V>) -> Self {
ValueDef::Composite(vals.into())
}
}
impl<V: Into<Value<()>>> From<Vec<V>> for Value<()> {
fn from(vals: Vec<V>) -> Self {
Value::without_context(vals.into())
}
}
impl<K: Into<String>, V: Into<Value<()>>> From<Vec<(K, V)>> for Composite<()> {
fn from(vals: Vec<(K, V)>) -> Self {
let vals = vals.into_iter().map(|(k, v)| (k.into(), v.into())).collect();
Composite::Named(vals)
}
}
impl<K: Into<String>, V: Into<Value<()>>> From<Vec<(K, V)>> for ValueDef<()> {
fn from(vals: Vec<(K, V)>) -> Self {
ValueDef::Composite(vals.into())
}
}
impl<K: Into<String>, V: Into<Value<()>>> From<Vec<(K, V)>> for Value<()> {
fn from(vals: Vec<(K, V)>) -> Self {
Value::without_context(vals.into())
}
}
impl<T> From<Composite<T>> for ValueDef<T> {
fn from(val: Composite<T>) -> Self {
ValueDef::Composite(val)
}
}
impl From<Composite<()>> for Value<()> {
fn from(val: Composite<()>) -> Self {
Value::without_context(ValueDef::Composite(val))
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Variant<T> {
pub name: String,
pub values: Composite<T>,
}
impl<T> Variant<T> {
pub fn named_fields<S, K, Vals>(name: S, fields: Vals) -> Variant<T>
where
S: Into<String>,
K: Into<String>,
Vals: IntoIterator<Item = (K, Value<T>)>,
{
Variant { name: name.into(), values: Composite::named(fields) }
}
pub fn unnamed_fields<S, Vals>(name: S, fields: Vals) -> Variant<T>
where
S: Into<String>,
Vals: IntoIterator<Item = Value<T>>,
{
Variant { name: name.into(), values: Composite::unnamed(fields) }
}
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> From<Variant<T>> for ValueDef<T> {
fn from(val: Variant<T>) -> Self {
ValueDef::Variant(val)
}
}
impl From<Variant<()>> for Value<()> {
fn from(val: Variant<()>) -> Self {
Value::without_context(ValueDef::Variant(val))
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Primitive {
Bool(bool),
Char(char),
String(String),
U128(u128),
I128(i128),
U256([u8; 32]),
I256([u8; 32]),
}
impl Primitive {
pub fn u128(val: u128) -> Primitive {
Primitive::U128(val)
}
pub fn i128(val: i128) -> Primitive {
Primitive::I128(val)
}
pub fn as_bool(&self) -> Option<bool> {
match self {
Primitive::Bool(b) => Some(*b),
_ => None,
}
}
pub fn as_char(&self) -> Option<char> {
match self {
Primitive::Char(c) => Some(*c),
_ => None,
}
}
pub fn as_u128(&self) -> Option<u128> {
match self {
Primitive::U128(n) => Some(*n),
_ => None,
}
}
pub fn as_i128(&self) -> Option<i128> {
match self {
Primitive::I128(n) => Some(*n),
_ => None,
}
}
pub fn as_str(&self) -> Option<&str> {
match self {
Primitive::String(s) => Some(&**s),
_ => None,
}
}
}
impl<T> From<Primitive> for ValueDef<T> {
fn from(val: Primitive) -> Self {
ValueDef::Primitive(val)
}
}
macro_rules! impl_primitive_type {
($($variant:ident($ty:ty as $castty:ty),)*) => {$(
impl From<$ty> for Primitive {
fn from(val: $ty) -> Self {
Primitive::$variant(val as $castty)
}
}
impl<T> From<$ty> for ValueDef<T> {
fn from(val: $ty) -> Self {
ValueDef::Primitive(val.into())
}
}
impl From<$ty> for Value<()> {
fn from(val: $ty) -> Self {
Value::without_context(val.into())
}
}
)*}
}
impl_primitive_type!(
Bool(bool as bool),
Char(char as char),
String(String as String),
U128(u128 as u128),
U128(u64 as u128),
U128(usize as u128),
U128(u32 as u128),
U128(u16 as u128),
U128(u8 as u128),
I128(i128 as i128),
I128(i64 as i128),
I128(isize as i128),
I128(i32 as i128),
I128(i16 as i128),
I128(i8 as i128),
);
impl From<&str> for Primitive {
fn from(val: &str) -> Self {
Primitive::String(val.to_string())
}
}
impl<T> From<&str> for ValueDef<T> {
fn from(val: &str) -> Self {
ValueDef::Primitive(val.into())
}
}
impl From<&str> for Value<()> {
fn from(val: &str) -> Self {
Value::without_context(val.into())
}
}