use qubit_datatype::DataType;
use crate::IntoValueDefault;
use crate::value_error::{
ValueError,
ValueResult,
};
use super::multi_values::MultiValues;
macro_rules! multi_values_data_type_match {
($value:expr; $(($variant:ident, $type:ty, $data_type:expr)),+ $(,)?) => {
match $value {
MultiValues::Empty(dt) => *dt,
$(MultiValues::$variant(_) => $data_type,)+
}
};
}
macro_rules! multi_values_count_match {
($value:expr; $(($variant:ident, $type:ty, $data_type:expr)),+ $(,)?) => {
match $value {
MultiValues::Empty(_) => 0,
$(MultiValues::$variant(values) => values.len(),)+
}
};
}
macro_rules! multi_values_clear_match {
($value:expr; $(($variant:ident, $type:ty, $data_type:expr)),+ $(,)?) => {
match $value {
MultiValues::Empty(_) => {}
$(MultiValues::$variant(values) => values.clear(),)+
}
};
}
macro_rules! multi_values_append_match {
($left:expr, $right:expr; $(($variant:ident, $type:ty, $data_type:expr)),+ $(,)?) => {
match ($left, $right) {
$(
(MultiValues::$variant(values), MultiValues::$variant(mut other_values)) => {
values.append(&mut other_values);
}
)+
(slot @ MultiValues::Empty(_), other_values) => *slot = other_values,
_ => unreachable!(),
}
};
}
impl MultiValues {
#[inline]
pub fn new<S>(values: S) -> Self
where
S: Into<Self>,
{
values.into()
}
#[inline]
pub fn get<T>(&self) -> ValueResult<Vec<T>>
where
for<'a> Vec<T>: TryFrom<&'a Self, Error = ValueError>,
{
Vec::<T>::try_from(self)
}
#[inline]
pub fn get_or<T>(&self, default: impl IntoValueDefault<Vec<T>>) -> ValueResult<Vec<T>>
where
for<'a> Vec<T>: TryFrom<&'a Self, Error = ValueError>,
{
let values = self.get()?;
if values.is_empty() {
Ok(default.into_value_default())
} else {
Ok(values)
}
}
#[inline]
pub fn get_first<T>(&self) -> ValueResult<T>
where
for<'a> T: TryFrom<&'a Self, Error = ValueError>,
{
T::try_from(self)
}
#[inline]
pub fn get_first_or<T>(&self, default: impl IntoValueDefault<T>) -> ValueResult<T>
where
for<'a> T: TryFrom<&'a Self, Error = ValueError>,
{
match self.get_first() {
Err(ValueError::NoValue) => Ok(default.into_value_default()),
result => result,
}
}
#[inline]
pub fn set<S>(&mut self, values: S) -> ValueResult<()>
where
S: Into<Self>,
{
*self = values.into();
Ok(())
}
#[inline]
pub fn add<S>(&mut self, values: S) -> ValueResult<()>
where
S: Into<Self>,
{
let other = values.into();
if self.data_type() != other.data_type() {
return Err(ValueError::TypeMismatch {
expected: self.data_type(),
actual: other.data_type(),
});
}
if other.count() == 0 {
return Ok(());
}
for_each_multi_value_type!(multi_values_append_match, self, other);
Ok(())
}
#[inline]
pub fn data_type(&self) -> DataType {
for_each_multi_value_type!(multi_values_data_type_match, self)
}
#[inline]
pub fn count(&self) -> usize {
for_each_multi_value_type!(multi_values_count_match, self)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.count() == 0
}
#[inline]
pub fn clear(&mut self) {
for_each_multi_value_type!(multi_values_clear_match, self)
}
#[inline]
pub fn set_type(&mut self, data_type: DataType) {
if self.data_type() != data_type {
*self = MultiValues::Empty(data_type);
}
}
}