use crate::algebraic_value::AlgebraicValue;
use crate::product_type::ProductType;
#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq, Hash)]
pub struct ProductValue {
pub elements: Vec<AlgebraicValue>,
}
#[macro_export]
macro_rules! product {
[$($elems:expr),*$(,)?] => {
$crate::ProductValue {
elements: vec![$($crate::AlgebraicValue::from($elems)),*]
}
}
}
impl ProductValue {
pub fn new(elements: &[AlgebraicValue]) -> Self {
Self {
elements: elements.into(),
}
}
}
impl FromIterator<AlgebraicValue> for ProductValue {
fn from_iter<T: IntoIterator<Item = AlgebraicValue>>(iter: T) -> Self {
let elements = iter.into_iter().collect();
Self { elements }
}
}
impl crate::Value for ProductValue {
type Type = ProductType;
}
#[derive(thiserror::Error, Debug, Copy, Clone)]
#[error("Field {index}({name:?}) not found or has an invalid type")]
pub struct InvalidFieldError {
pub index: usize,
pub name: Option<&'static str>,
}
impl ProductValue {
pub fn get_field(&self, index: usize, name: Option<&'static str>) -> Result<&AlgebraicValue, InvalidFieldError> {
self.elements.get(index).ok_or(InvalidFieldError { index, name })
}
pub fn extract_field<'a, T>(
&'a self,
index: usize,
name: Option<&'static str>,
f: impl 'a + Fn(&'a AlgebraicValue) -> Option<T>,
) -> Result<T, InvalidFieldError> {
f(self.get_field(index, name)?).ok_or(InvalidFieldError { index, name })
}
pub fn field_as_bool(&self, index: usize, named: Option<&'static str>) -> Result<bool, InvalidFieldError> {
self.extract_field(index, named, |f| f.as_bool().copied())
}
pub fn field_as_u8(&self, index: usize, named: Option<&'static str>) -> Result<u8, InvalidFieldError> {
self.extract_field(index, named, |f| f.as_u8().copied())
}
pub fn field_as_u32(&self, index: usize, named: Option<&'static str>) -> Result<u32, InvalidFieldError> {
self.extract_field(index, named, |f| f.as_u32().copied())
}
pub fn field_as_i64(&self, index: usize, named: Option<&'static str>) -> Result<i64, InvalidFieldError> {
self.extract_field(index, named, |f| f.as_i64().copied())
}
pub fn field_as_i128(&self, index: usize, named: Option<&'static str>) -> Result<i128, InvalidFieldError> {
self.extract_field(index, named, |f| f.as_i128().copied())
}
pub fn field_as_u128(&self, index: usize, named: Option<&'static str>) -> Result<u128, InvalidFieldError> {
self.extract_field(index, named, |f| f.as_u128().copied())
}
pub fn field_as_str(&self, index: usize, named: Option<&'static str>) -> Result<&str, InvalidFieldError> {
self.extract_field(index, named, |f| f.as_string().map(|x| x.as_str()))
}
pub fn field_as_bytes(&self, index: usize, named: Option<&'static str>) -> Result<&[u8], InvalidFieldError> {
self.extract_field(index, named, |f| f.as_bytes().map(|x| x.as_slice()))
}
}