use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
use super::error::Error;
use super::utils::for_each_tuple;
use crate::flatbuffer_wrappers::function_types::{ParameterType, ParameterValue};
pub trait SupportedParameterType: Sized + Clone + Send + Sync + 'static {
const TYPE: ParameterType;
fn into_value(self) -> ParameterValue;
fn from_value(value: ParameterValue) -> Result<Self, Error>;
}
macro_rules! for_each_param_type {
($macro:ident) => {
$macro!(String, String);
$macro!(i32, Int);
$macro!(u32, UInt);
$macro!(i64, Long);
$macro!(u64, ULong);
$macro!(f32, Float);
$macro!(f64, Double);
$macro!(bool, Bool);
$macro!(Vec<u8>, VecBytes);
};
}
macro_rules! impl_supported_param_type {
($type:ty, $enum:ident) => {
impl SupportedParameterType for $type {
const TYPE: ParameterType = ParameterType::$enum;
fn into_value(self) -> ParameterValue {
ParameterValue::$enum(self)
}
fn from_value(value: ParameterValue) -> Result<Self, Error> {
match value {
ParameterValue::$enum(i) => Ok(i),
other => Err(Error::ParameterValueConversionFailure(
other.clone(),
stringify!($type),
)),
}
}
}
};
}
for_each_param_type!(impl_supported_param_type);
pub trait ParameterTuple: Sized + Clone + Send + Sync + 'static {
const SIZE: usize;
const TYPE: &[ParameterType];
fn into_value(self) -> Vec<ParameterValue>;
fn from_value(value: Vec<ParameterValue>) -> Result<Self, Error>;
}
impl<T: SupportedParameterType> ParameterTuple for T {
const SIZE: usize = 1;
const TYPE: &[ParameterType] = &[T::TYPE];
fn into_value(self) -> Vec<ParameterValue> {
vec![self.into_value()]
}
fn from_value(value: Vec<ParameterValue>) -> Result<Self, Error> {
match <[ParameterValue; 1]>::try_from(value) {
Ok([val]) => Ok(T::from_value(val)?),
Err(value) => Err(Error::UnexpectedNoOfArguments(value.len(), 1)),
}
}
}
macro_rules! impl_param_tuple {
([$N:expr] ($($name:ident: $param:ident),*)) => {
impl<$($param: SupportedParameterType),*> ParameterTuple for ($($param,)*) {
const SIZE: usize = $N;
const TYPE: &[ParameterType] = &[
$($param::TYPE),*
];
fn into_value(self) -> Vec<ParameterValue> {
let ($($name,)*) = self;
vec![$($name.into_value()),*]
}
fn from_value(value: Vec<ParameterValue>) -> Result<Self, Error> {
match <[ParameterValue; $N]>::try_from(value) {
Ok([$($name,)*]) => Ok(($($param::from_value($name)?,)*)),
Err(value) => Err(Error::UnexpectedNoOfArguments(value.len(), $N))
}
}
}
};
}
for_each_tuple!(impl_param_tuple);