use std::convert::Infallible;
use std::fmt::{Debug, Display};
use std::borrow::Cow;
use std::{mem, slice};
use crate::array::{MdArray, MdView};
use crate::dev::DevState;
#[derive(Debug, Clone, Default)]
pub enum Data<'a> {
#[default]
Void,
Bool(DataLayout<'a, bool>),
Octet(DataLayout<'a, u8>),
UShort(DataLayout<'a, u16>),
Short(DataLayout<'a, i16>),
ULong(DataLayout<'a, u32>),
Long(DataLayout<'a, i32>),
ULong64(DataLayout<'a, u64>),
Long64(DataLayout<'a, i64>),
Float(DataLayout<'a, f32>),
Double(DataLayout<'a, f64>),
State(DataLayout<'a, DevState>),
String(DataLayout<'a, Cow<'a, str>>),
Struct(DataStruct<'a>),
}
#[derive(Debug, Clone)]
pub enum DataLayout<'a, T: 'a> {
Scalar(T),
ScalarView(&'a T),
Spectrum(MdArray<T, 1>),
SpectrumView(MdView<'a, T, 1>),
Image(MdArray<T, 2>),
ImageView(MdView<'a, T, 2>),
}
#[derive(Debug, Clone)]
pub enum DataStruct<'a> {
Owned(Box<[Data<'a>]>),
View(&'a [Data<'a>]),
}
impl<'a> Data<'a> {
pub fn kind(&self) -> DataKind {
self.as_view().kind()
}
pub fn as_view(&self) -> DataView<'_> {
match self {
Data::Void => DataView::Void,
Data::Bool(data) => DataView::Bool(data.as_view()),
Data::Octet(data) => DataView::Octet(data.as_view()),
Data::UShort(data) => DataView::UShort(data.as_view()),
Data::Short(data) => DataView::Short(data.as_view()),
Data::ULong(data) => DataView::ULong(data.as_view()),
Data::Long(data) => DataView::Long(data.as_view()),
Data::ULong64(data) => DataView::ULong64(data.as_view()),
Data::Long64(data) => DataView::Long64(data.as_view()),
Data::Float(data) => DataView::Float(data.as_view()),
Data::Double(data) => DataView::Double(data.as_view()),
Data::State(data) => DataView::State(data.as_view()),
Data::String(data) => DataView::String(data.as_view()),
Data::Struct(data) => DataView::Struct(data.as_view()),
}
}
fn is_owned(&self) -> bool {
match self {
Data::Void => true,
Data::Bool(data) => data.is_owned(),
Data::Octet(data) => data.is_owned(),
Data::UShort(data) => data.is_owned(),
Data::Short(data) => data.is_owned(),
Data::ULong(data) => data.is_owned(),
Data::Long(data) => data.is_owned(),
Data::ULong64(data) => data.is_owned(),
Data::Long64(data) => data.is_owned(),
Data::Float(data) => data.is_owned(),
Data::Double(data) => data.is_owned(),
Data::State(data) => data.is_owned(),
Data::String(DataLayout::Scalar(Cow::Owned(_))) => true,
Data::String(DataLayout::Spectrum(arr)) => arr.as_raw_slice().iter().all(|s| matches!(s, Cow::Owned(_))),
Data::String(DataLayout::Image(arr)) => arr.as_raw_slice().iter().all(|s| matches!(s, Cow::Owned(_))),
Data::String(_) => false,
Data::Struct(DataStruct::View(_)) => false,
Data::Struct(DataStruct::Owned(data)) => data.iter().all(|d| d.is_owned()),
}
}
pub fn to_owned(self) -> Result<Data<'static>, Self> {
if self.is_owned() {
Ok(unsafe { mem::transmute(self) })
} else {
Err(self)
}
}
pub fn into_owned(self) -> Data<'static> {
match self {
Data::Void => Data::Void,
Data::Bool(data) => Data::Bool(data.into_owned()),
Data::Octet(data) => Data::Octet(data.into_owned()),
Data::UShort(data) => Data::UShort(data.into_owned()),
Data::Short(data) => Data::Short(data.into_owned()),
Data::ULong(data) => Data::ULong(data.into_owned()),
Data::Long(data) => Data::Long(data.into_owned()),
Data::ULong64(data) => Data::ULong64(data.into_owned()),
Data::Long64(data) => Data::Long64(data.into_owned()),
Data::Float(data) => Data::Float(data.into_owned()),
Data::Double(data) => Data::Double(data.into_owned()),
Data::State(data) => Data::State(data.into_owned()),
Data::String(DataLayout::Scalar(v)) =>
Data::String(DataLayout::Scalar(Cow::Owned(v.to_string()))),
Data::String(DataLayout::ScalarView(v)) =>
Data::String(DataLayout::Scalar(Cow::Owned(v.to_string()))),
Data::String(DataLayout::Spectrum(v)) =>
Data::String(DataLayout::Spectrum(v.map(|v| Cow::Owned(v.into_owned())))),
Data::String(DataLayout::SpectrumView(v)) =>
Data::String(DataLayout::Spectrum(v.map_to_owned(|v| Cow::Owned(v.to_string())))),
Data::String(DataLayout::Image(v)) =>
Data::String(DataLayout::Image(v.map(|v| Cow::Owned(v.into_owned())))),
Data::String(DataLayout::ImageView(v)) =>
Data::String(DataLayout::Image(v.map_to_owned(|v| Cow::Owned(v.to_string())))),
Data::Struct(DataStruct::Owned(data)) => Data::Struct(DataStruct::Owned(data.into_iter()
.map(|data| data.into_owned())
.collect::<Box<[_]>>())),
Data::Struct(DataStruct::View(data)) => Data::Struct(DataStruct::Owned(data.iter()
.map(|data| data.clone().into_owned())
.collect::<Box<[_]>>()))
}
}
}
impl<'a, T: 'a> DataLayout<'a, T> {
pub fn as_view(&self) -> DataLayoutView<'_, T> {
match self {
DataLayout::Scalar(v) => DataLayoutView::Scalar(v),
&DataLayout::ScalarView(v) => DataLayoutView::Scalar(v),
DataLayout::Spectrum(v) => DataLayoutView::Spectrum(v.as_view()),
&DataLayout::SpectrumView(v) => DataLayoutView::Spectrum(v),
DataLayout::Image(v) => DataLayoutView::Image(v.as_view()),
&DataLayout::ImageView(v) => DataLayoutView::Image(v),
}
}
fn is_owned(&self) -> bool {
match self {
DataLayout::Scalar(_) |
DataLayout::Spectrum(_) |
DataLayout::Image(_) => true,
DataLayout::ScalarView(_) |
DataLayout::SpectrumView(_) |
DataLayout::ImageView(_) => false,
}
}
pub(crate) fn map_view_to_owned<U, F: FnMut(&'a T) -> U>(self, mut func: F) -> DataLayout<'a, U> {
match self {
DataLayout::Scalar(_) => panic!("this function only works on views"),
DataLayout::ScalarView(v) => DataLayout::Scalar(func(v)),
DataLayout::Spectrum(_) => panic!("this function only works on views"),
DataLayout::SpectrumView(v) => DataLayout::Spectrum(v.map_to_owned(func)),
DataLayout::Image(_) => panic!("this function only works on views"),
DataLayout::ImageView(v) => DataLayout::Image(v.map_to_owned(func)),
}
}
}
impl<'a, T: 'a + Clone> DataLayout<'a, T> {
fn into_owned(self) -> DataLayout<'static, T> {
match self {
DataLayout::Scalar(v) => DataLayout::Scalar(v),
DataLayout::ScalarView(v) => DataLayout::Scalar(v.clone()),
DataLayout::Spectrum(v) => DataLayout::Spectrum(v),
DataLayout::SpectrumView(v) => DataLayout::Spectrum(v.to_owned()),
DataLayout::Image(v) => DataLayout::Image(v),
DataLayout::ImageView(v) => DataLayout::Image(v.to_owned()),
}
}
}
impl DataStruct<'_> {
#[inline]
pub fn as_view(&self) -> DataStructView<'_> {
match self {
DataStruct::Owned(fields) => DataStructView { raw: &fields[..] },
DataStruct::View(fields) => DataStructView { raw: *fields },
}
}
#[inline]
pub fn len(&self) -> usize {
self.as_view().len()
}
}
#[derive(Debug, Clone)]
pub enum DataView<'a> {
Void,
Bool(DataLayoutView<'a, bool>),
Octet(DataLayoutView<'a, u8>),
UShort(DataLayoutView<'a, u16>),
Short(DataLayoutView<'a, i16>),
ULong(DataLayoutView<'a, u32>),
Long(DataLayoutView<'a, i32>),
ULong64(DataLayoutView<'a, u64>),
Long64(DataLayoutView<'a, i64>),
Float(DataLayoutView<'a, f32>),
Double(DataLayoutView<'a, f64>),
State(DataLayoutView<'a, DevState>),
String(DataLayoutView<'a, Cow<'a, str>>),
Struct(DataStructView<'a>),
}
#[derive(Debug, Clone, Copy)]
pub enum DataLayoutView<'a, T: 'a> {
Scalar(&'a T),
Spectrum(MdView<'a, T, 1>),
Image(MdView<'a, T, 2>),
}
#[derive(Debug, Clone)]
pub struct DataStructView<'a> {
raw: &'a [Data<'a>],
}
impl<'a> DataView<'a> {
pub fn kind(&self) -> DataKind {
match self {
DataView::Void => DataKind::Void,
DataView::Bool(layout) => DataKind::Bool(layout.kind()),
DataView::Octet(layout) => DataKind::Octet(layout.kind()),
DataView::UShort(layout) => DataKind::UShort(layout.kind()),
DataView::Short(layout) => DataKind::Short(layout.kind()),
DataView::ULong(layout) => DataKind::ULong(layout.kind()),
DataView::Long(layout) => DataKind::Long(layout.kind()),
DataView::ULong64(layout) => DataKind::ULong64(layout.kind()),
DataView::Long64(layout) => DataKind::Long64(layout.kind()),
DataView::Float(layout) => DataKind::Float(layout.kind()),
DataView::Double(layout) => DataKind::Double(layout.kind()),
DataView::State(layout) => DataKind::State(layout.kind()),
DataView::String(layout) => DataKind::String(layout.kind()),
DataView::Struct(fields) => DataKind::Struct(Cow::Owned(fields.raw.iter()
.map(|data| data.as_view().kind())
.collect::<Vec<_>>())),
}
}
pub fn into_owned(self) -> Data<'a> {
match self {
DataView::Void => Data::Void,
DataView::Bool(data) => Data::Bool(data.into_owned()),
DataView::Octet(data) => Data::Octet(data.into_owned()),
DataView::UShort(data) => Data::UShort(data.into_owned()),
DataView::Short(data) => Data::Short(data.into_owned()),
DataView::ULong(data) => Data::ULong(data.into_owned()),
DataView::Long(data) => Data::Long(data.into_owned()),
DataView::ULong64(data) => Data::ULong64(data.into_owned()),
DataView::Long64(data) => Data::Long64(data.into_owned()),
DataView::Float(data) => Data::Float(data.into_owned()),
DataView::Double(data) => Data::Double(data.into_owned()),
DataView::State(data) => Data::State(data.into_owned()),
DataView::String(data) => Data::String(data.into_owned()),
DataView::Struct(data) => Data::Struct(DataStruct::View(data.raw)),
}
}
}
impl<'a, T: 'a> DataLayoutView<'a, T> {
pub fn kind(&self) -> DataLayoutKind {
match self {
DataLayoutView::Scalar(_) =>
DataLayoutKind::Scalar,
DataLayoutView::Spectrum(arr) =>
DataLayoutKind::Spectrum(Some(arr.len(0))),
DataLayoutView::Image(arr) =>
DataLayoutKind::Image(Some((arr.len(0), arr.len(1)))),
}
}
fn into_owned(self) -> DataLayout<'a, T> {
match self {
DataLayoutView::Scalar(v) => DataLayout::ScalarView(v),
DataLayoutView::Spectrum(v) => DataLayout::SpectrumView(v),
DataLayoutView::Image(v) => DataLayout::ImageView(v),
}
}
pub fn as_slice(&self) -> &[T] {
match *self {
DataLayoutView::Scalar(v) => slice::from_ref(v),
DataLayoutView::Spectrum(v) => v.as_raw_slice(),
DataLayoutView::Image(v) => v.as_raw_slice(),
}
}
pub fn as_scalar(&self) -> Option<&T> {
match *self {
DataLayoutView::Scalar(v) => Some(v),
_ => None,
}
}
pub fn as_spectrum(&self) -> Option<MdView<'_, T, 1>> {
match *self {
DataLayoutView::Spectrum(v) => Some(v),
_ => return None
}
}
pub fn as_image(&self) -> Option<MdView<'_, T, 2>> {
match *self {
DataLayoutView::Image(v) => Some(v),
_ => return None
}
}
}
impl<'a> DataStructView<'a> {
#[inline]
pub fn len(&self) -> usize {
self.raw.len()
}
#[inline]
pub fn get(&self, index: usize) -> Option<DataView<'_>> {
self.raw.get(index).map(|data| data.as_view())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum DataKind {
Unspecified,
Void,
Bool(DataLayoutKind),
Octet(DataLayoutKind),
UShort(DataLayoutKind),
Short(DataLayoutKind),
ULong(DataLayoutKind),
Long(DataLayoutKind),
ULong64(DataLayoutKind),
Long64(DataLayoutKind),
Float(DataLayoutKind),
Double(DataLayoutKind),
State(DataLayoutKind),
String(DataLayoutKind),
Enum(Cow<'static, [String]>),
Struct(Cow<'static, [DataKind]>),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum DataLayoutKind {
Unspecified,
Scalar,
Spectrum(Option<usize>),
Image(Option<(usize, usize)>),
}
pub trait IntoData<'d>: Sized {
const DATA_KIND: DataKind = DataKind::Unspecified;
fn into_data(self) -> Data<'d>;
}
pub trait FromData<'d>: Sized {
const DATA_KIND: DataKind = DataKind::Unspecified;
type Err: Display + Debug;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err>;
}
impl<'d> IntoData<'d> for Data<'d> {
fn into_data(self) -> Data<'d> {
self
}
}
impl<'d: 'dd, 'dd> FromData<'d> for Data<'dd> {
type Err = Infallible;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
Ok(data)
}
}
impl IntoData<'static> for () {
const DATA_KIND: DataKind = DataKind::Void;
fn into_data(self) -> Data<'static> {
Data::Void
}
}
impl<'d> FromData<'d> for () {
const DATA_KIND: DataKind = DataKind::Void;
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::Void => Ok(()),
_ => Err(format!("Data should be a Void to make a (): {data:?}")),
}
}
}
macro_rules! impl_data_for_tuple {
( @one: $comp:ident ) => { 1 };
( $( $comp:ident )* ) => {
#[allow(unused_assignments, non_snake_case)]
impl<'d $(, $comp)* > IntoData<'d> for ( $($comp,)* )
where
$(
$comp: IntoData<'d>,
)*
{
const DATA_KIND: DataKind = DataKind::Struct(Cow::Borrowed(&[
$(<$comp>::DATA_KIND,)*
]));
#[inline]
fn into_data(self) -> Data<'d> {
let ( $($comp,)* ): ( $($comp,)* ) = self;
Data::Struct(DataStruct::Owned(Box::new([
$($comp.into_data(),)*
])))
}
}
#[allow(unused_assignments, non_snake_case)]
impl<'d $(, $comp)* > FromData<'d> for ( $($comp,)* )
where
$(
$comp: FromData<'d>,
)*
{
const DATA_KIND: DataKind = DataKind::Struct(Cow::Borrowed(&[
$(<$comp>::DATA_KIND,)*
]));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
const EXPECTED_LEN: usize = 0 $( + impl_data_for_tuple!(@one: $comp) )*;
let mut data = match data {
Data::Struct(DataStruct::Owned(data)) if data.len() == EXPECTED_LEN => data,
Data::Struct(DataStruct::View(data)) if data.len() == EXPECTED_LEN => data.to_vec().into_boxed_slice(),
_ => return Err(format!("Data should be a Struct of length {EXPECTED_LEN} to make a tuple: {data:?}")),
};
let [$($comp,)*] = &mut data[..] else { unreachable!() };
let mut index = 0usize;
Ok((
$(
match $comp::from_data(mem::replace($comp, Data::Void)) {
Ok(val) => {
index += 1;
val
}
Err(err) => return Err(format!("Data.{index}: {err}")),
},
)*
))
}
}
};
}
impl_data_for_tuple!(A);
impl_data_for_tuple!(A B);
impl_data_for_tuple!(A B C);
impl_data_for_tuple!(A B C D);
impl_data_for_tuple!(A B C D E);
impl_data_for_tuple!(A B C D E F);
macro_rules! impl_data_for_copy {
( $ty:ty, $data_variant:ident ) => {
impl IntoData<'static> for $ty {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Scalar);
#[inline]
fn into_data(self) -> Data<'static> {
Data::$data_variant(DataLayout::Scalar(self))
}
}
impl<'d> IntoData<'d> for MdView<'d, $ty, 0> {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Scalar);
#[inline]
fn into_data(self) -> Data<'d> {
Data::$data_variant(DataLayout::ScalarView(self.get([]).unwrap()))
}
}
impl<'d> IntoData<'d> for MdView<'d, $ty, 1> {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Spectrum(None));
#[inline]
fn into_data(self) -> Data<'d> {
Data::$data_variant(DataLayout::SpectrumView(self))
}
}
impl<'d> IntoData<'d> for MdView<'d, $ty, 2> {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Image(None));
#[inline]
fn into_data(self) -> Data<'d> {
Data::$data_variant(DataLayout::ImageView(self))
}
}
impl<'d> IntoData<'d> for &'d [$ty] {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Spectrum(None));
#[inline]
fn into_data(self) -> Data<'d> {
MdView::from(self).into_data()
}
}
impl<'d> FromData<'d> for $ty {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Scalar);
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::$data_variant(DataLayout::Scalar(val)) => Ok(val),
Data::$data_variant(DataLayout::ScalarView(val)) => Ok(*val),
_ => Err(format!(concat!("Data should be a ", stringify!($data_variant), " scalar to make a ", stringify!($ty) ,": {:?}"), data)),
}
}
}
impl<'d: 'dd, 'dd> FromData<'d> for &'dd $ty {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Scalar);
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::$data_variant(DataLayout::ScalarView(val)) => Ok(val),
_ => Err(format!(concat!("Data should be a ", stringify!($data_variant), " scalar to make a ", stringify!(&$ty) ,": {:?}"), data)),
}
}
}
impl<'d: 'dd, 'dd> FromData<'d> for &'dd [$ty] {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Spectrum(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::$data_variant(DataLayout::SpectrumView(val)) => Ok(val.as_raw_slice()),
_ => Err(format!(concat!("Data should be a ", stringify!($data_variant), " spectrum (view) to make a ", stringify!(&[$ty]) ,": {:?}"), data)),
}
}
}
impl<'d: 'dd, 'dd> FromData<'d> for MdView<'dd, $ty, 0> {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Scalar);
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::$data_variant(DataLayout::ScalarView(val)) => Ok(MdView::from(val)),
_ => Err(format!(concat!("Data should be a ", stringify!($data_variant), " scalar (view) to make a ", stringify!(MdView<$ty, 0>) ,": {:?}"), data)),
}
}
}
impl<'d: 'dd, 'dd> FromData<'d> for MdView<'dd, $ty, 1> {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Spectrum(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::$data_variant(DataLayout::SpectrumView(val)) => Ok(MdView::from(val)),
_ => Err(format!(concat!("Data should be a ", stringify!($data_variant), " spectrum (view) to make a ", stringify!(MdView<$ty, 1>) ,": {:?}"), data)),
}
}
}
impl<'d: 'dd, 'dd> FromData<'d> for MdView<'dd, $ty, 2> {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Image(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::$data_variant(DataLayout::ImageView(val)) => Ok(MdView::from(val)),
_ => Err(format!(concat!("Data should be a ", stringify!($data_variant), " image (view) to make a ", stringify!(MdView<$ty, 2>) ,": {:?}"), data)),
}
}
}
impl<'d> FromData<'d> for MdArray<$ty, 0> {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Scalar);
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::$data_variant(DataLayout::Scalar(val)) => Ok(MdArray::from(val)),
Data::$data_variant(DataLayout::ScalarView(val)) => Ok(MdView::from(val).to_owned()),
_ => Err(format!(concat!("Data should be a ", stringify!($data_variant), " scalar to make a ", stringify!(MdArray<$ty, 0>) ,": {:?}"), data)),
}
}
}
impl<'d> FromData<'d> for MdArray<$ty, 1> {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Spectrum(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::$data_variant(DataLayout::Spectrum(val)) => Ok(val),
Data::$data_variant(DataLayout::SpectrumView(val)) => Ok(val.to_owned()),
_ => Err(format!(concat!("Data should be a ", stringify!($data_variant), " spectrum to make a ", stringify!(MdArray<$ty, 1>) ,": {:?}"), data)),
}
}
}
impl<'d> FromData<'d> for MdArray<$ty, 2> {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Image(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::$data_variant(DataLayout::Image(val)) => Ok(val),
Data::$data_variant(DataLayout::ImageView(val)) => Ok(val.to_owned()),
_ => Err(format!(concat!("Data should be a ", stringify!($data_variant), " image to make a ", stringify!(MdArray<$ty, 2>) ,": {:?}"), data)),
}
}
}
impl<'d> FromData<'d> for Box<[$ty]> {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Spectrum(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
<MdArray<$ty, 1>>::from_data(data).map(|arr| arr.into_boxed_slice())
}
}
impl<'d, const N: usize> FromData<'d> for Box<[$ty; N]> {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Spectrum(Some(N)));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
<Box<[$ty]>>::from_data(data)
.and_then(|arr| arr.try_into()
.map_err(|_| format!(concat!("Data should be a ", stringify!($data_variant), " spectrum of len {} to make a ", stringify!(Box<[$ty; N]>)), N)))
}
}
impl<'d> FromData<'d> for Vec<$ty> {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Spectrum(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
<Box<[$ty]>>::from_data(data).map(|arr| arr.to_vec())
}
}
impl<'d, const N: usize> FromData<'d> for [$ty; N] {
const DATA_KIND: DataKind = DataKind::$data_variant(DataLayoutKind::Spectrum(Some(N)));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
<Box<[$ty; N]>>::from_data(data).map(|arr| *arr)
}
}
};
}
impl_data_for_copy!(bool, Bool);
impl_data_for_copy!(u16, UShort);
impl_data_for_copy!(i16, Short);
impl_data_for_copy!(u32, ULong);
impl_data_for_copy!(i32, Long);
impl_data_for_copy!(u64, ULong64);
impl_data_for_copy!(i64, Long64);
impl_data_for_copy!(f32, Float);
impl_data_for_copy!(f64, Double);
impl_data_for_copy!(DevState, State);
impl<'d> IntoData<'d> for Cow<'d, str> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Scalar);
#[inline]
fn into_data(self) -> Data<'d> {
Data::String(DataLayout::Scalar(self))
}
}
impl<'d> IntoData<'d> for &'d str {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Scalar);
#[inline]
fn into_data(self) -> Data<'d> {
Cow::Borrowed(self).into_data()
}
}
impl<'d> IntoData<'d> for &'d [Cow<'d, str>] {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(None));
#[inline]
fn into_data(self) -> Data<'d> {
Data::String(DataLayout::SpectrumView(self.into()))
}
}
impl<'d> IntoData<'d> for Vec<Cow<'d, str>> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(None));
#[inline]
fn into_data(self) -> Data<'d> {
Data::String(DataLayout::Spectrum(self.into()))
}
}
impl<'d> IntoData<'d> for Box<[Cow<'d, str>]> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(None));
#[inline]
fn into_data(self) -> Data<'d> {
Data::String(DataLayout::Spectrum(self.into()))
}
}
impl<'d, const N: usize> IntoData<'d> for [Cow<'d, str>; N] {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(Some(N)));
#[inline]
fn into_data(self) -> Data<'d> {
Data::String(DataLayout::Spectrum(self.into()))
}
}
impl<'d> IntoData<'d> for &'d [&'d str] {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(None));
#[inline]
fn into_data(self) -> Data<'d> {
self.into_iter()
.copied()
.map(Cow::Borrowed)
.collect::<Box<[_]>>()
.into_data()
}
}
impl<'d> IntoData<'d> for Vec<&'d str> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(None));
#[inline]
fn into_data(self) -> Data<'d> {
self.into_iter()
.map(Cow::Borrowed)
.collect::<Box<[_]>>()
.into_data()
}
}
impl<'d> IntoData<'d> for Box<[&'d str]> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(None));
#[inline]
fn into_data(self) -> Data<'d> {
self.into_vec().into_data()
}
}
impl<'d, const N: usize> IntoData<'d> for [&'d str; N] {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(Some(N)));
#[inline]
fn into_data(self) -> Data<'d> {
Box::<[&'d str]>::from(self).into_data()
}
}
impl<'d: 'dd, 'dd> FromData<'d> for Cow<'dd, str> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Scalar);
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::String(DataLayout::Scalar(val)) => Ok(val),
Data::String(DataLayout::ScalarView(val)) => Ok(val.clone()),
_ => Err(format!("Data should be a String scalar to make a Cow<'d_, str>: {data:?}")),
}
}
}
impl<'d: 'dd, 'dd> FromData<'d> for MdArray<Cow<'dd, str>, 0> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Scalar);
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
Cow::<'dd, str>::from_data(data).map(|data| data.into())
}
}
impl<'d: 'dd, 'dd> FromData<'d> for MdArray<Cow<'dd, str>, 1> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::String(DataLayout::Spectrum(val)) => Ok(val),
Data::String(DataLayout::SpectrumView(val)) => Ok(val.to_owned()),
_ => Err(format!("Data should be a String spectrum to make a MdArray<Cow<str>, 1>: {data:?}")),
}
}
}
impl<'d: 'dd, 'dd> FromData<'d> for MdArray<Cow<'dd, str>, 2> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Image(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::String(DataLayout::Image(val)) => Ok(val),
Data::String(DataLayout::ImageView(val)) => Ok(val.to_owned()),
_ => Err(format!("Data should be a String image to make a MdArray<Cow<str>, 2>: {data:?}")),
}
}
}
impl<'d: 'dd, 'dd> FromData<'d> for Box<[Cow<'dd, str>]> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
<MdArray<Cow<'dd, str>, 1>>::from_data(data).map(MdArray::into_boxed_slice)
}
}
impl<'d: 'dd, 'dd> FromData<'d> for Vec<Cow<'dd, str>> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
<Box<[Cow<'dd, str>]>>::from_data(data).map(<[Cow<'dd, str>]>::into_vec)
}
}
impl<'d> FromData<'d> for String {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Scalar);
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
<Cow<'_, str>>::from_data(data).map(|v| v.into_owned())
}
}
impl<'d> FromData<'d> for MdArray<String, 0> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Scalar);
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
String::from_data(data).map(|data| data.into())
}
}
impl<'d> FromData<'d> for MdArray<String, 1> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::String(DataLayout::Spectrum(val)) => Ok(val.map(Cow::into_owned)),
Data::String(DataLayout::SpectrumView(val)) => Ok(val.map_to_owned(ToString::to_string)),
_ => Err(format!("Data should be a String spectrum to make a MdArray<String, 1>: {data:?}")),
}
}
}
impl<'d> FromData<'d> for MdArray<String, 2> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Image(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::String(DataLayout::Image(val)) => Ok(val.map(Cow::into_owned)),
Data::String(DataLayout::ImageView(val)) => Ok(val.map_to_owned(ToString::to_string)),
_ => Err(format!("Data should be a String image to make a MdArray<String, 2>: {data:?}")),
}
}
}
impl<'d> FromData<'d> for Box<[String]> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
<MdArray<String, 1>>::from_data(data).map(MdArray::into_boxed_slice)
}
}
impl<'d> FromData<'d> for Vec<String> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Spectrum(None));
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
<Box<[String]>>::from_data(data).map(<[String]>::into_vec)
}
}
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Concat<T>(pub T);
impl<'d: 'dd, 'dd> FromData<'d> for Concat<Cow<'dd, str>> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Scalar);
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
match data {
Data::String(DataLayout::Scalar(val)) => Ok(Concat(val)),
Data::String(DataLayout::ScalarView(val)) => Ok(Concat(val.clone())),
Data::String(DataLayout::Spectrum(_)) |
Data::String(DataLayout::SpectrumView(_)) => {
let val = match data {
Data::String(DataLayout::Spectrum(ref val)) => val.as_view(),
Data::String(DataLayout::SpectrumView(val)) => val,
_ => unreachable!()
};
let concat = val.as_raw_slice()
.into_iter()
.fold(String::new(), |mut acc, item| {
if !acc.is_empty() {
acc.push('\n');
}
acc.push_str(&item);
acc
});
Ok(Concat(Cow::Owned(concat)))
}
_ => Err(format!("Data should be a String scalar/spectrum to be concatenated into one string: {data:?}")),
}
}
}
impl<'d> FromData<'d> for Concat<String> {
const DATA_KIND: DataKind = DataKind::String(DataLayoutKind::Scalar);
type Err = String;
fn from_data(data: Data<'d>) -> Result<Self, Self::Err> {
<Concat<Cow<'_, str>>>::from_data(data).map(|Concat(s)| Concat(s.into_owned()))
}
}