use either::Either;
use std::convert::From;
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),)*) => {$(
impl From<$ty> for Primitive {
fn from(val: $ty) -> Self {
Primitive::$variant(val)
}
}
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), Char(char), String(String), U128(u128), I128(i128),);