use crate::error::QuantusError;
use subxt::ext::scale_value::{Composite, Primitive, Value, ValueDef};
pub(crate) type Val = Value<u32>;
pub(crate) fn variant(v: &Val) -> Option<(&str, &Composite<u32>)> {
match &v.value {
ValueDef::Variant(var) => Some((var.name.as_str(), &var.values)),
_ => None,
}
}
pub(crate) fn composite(v: &Val) -> Option<&Composite<u32>> {
match &v.value {
ValueDef::Composite(c) => Some(c),
_ => None,
}
}
pub(crate) fn field<'a>(c: &'a Composite<u32>, name: &str) -> Option<&'a Val> {
match c {
Composite::Named(fields) => fields.iter().find(|(n, _)| n == name).map(|(_, v)| v),
Composite::Unnamed(_) => None,
}
}
pub(crate) fn nth(c: &Composite<u32>, i: usize) -> Option<&Val> {
match c {
Composite::Named(fields) => fields.get(i).map(|(_, v)| v),
Composite::Unnamed(fields) => fields.get(i),
}
}
pub(crate) fn uint(v: &Val) -> Option<u128> {
match &v.value {
ValueDef::Primitive(Primitive::U128(n)) => Some(*n),
ValueDef::Composite(c) => nth(c, 0).and_then(uint),
_ => None,
}
}
pub(crate) fn byte(v: &Val) -> Option<u8> {
match &v.value {
ValueDef::Primitive(Primitive::U128(n)) => u8::try_from(*n).ok(),
_ => None,
}
}
pub(crate) fn boolean(v: &Val) -> Option<bool> {
match &v.value {
ValueDef::Primitive(Primitive::Bool(b)) => Some(*b),
_ => None,
}
}
pub(crate) fn option(v: &Val) -> Option<Option<&Val>> {
let (name, inner) = variant(v)?;
match name {
"None" => Some(None),
"Some" => Some(Some(nth(inner, 0)?)),
_ => None,
}
}
pub(crate) fn missing(what: &str) -> QuantusError {
QuantusError::Generic(format!(
"decode: {what} is missing or has an unexpected shape; this runtime's pallet layout is \
not recognized"
))
}
pub(crate) fn u32_field(c: &Composite<u32>, name: &str) -> Result<u32, QuantusError> {
let raw = field(c, name).and_then(uint).ok_or_else(|| missing(name))?;
u32::try_from(raw).map_err(|_| missing(name))
}