use interface::UniqueIdentifier;
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
pub(crate) struct ScopeData<U: UniqueIdentifier>(PhantomData<U>);
impl<U: UniqueIdentifier> UniqueIdentifier for ScopeData<U> {
type DataType = Payload;
const PORT: u16 = U::PORT;
}
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize)]
pub(crate) enum Payload {
Signal {
tag: String,
tau: f64,
value: f64,
},
Signals {
tag: String,
tau: f64,
value: Vec<f64>,
},
Image {
tag: String,
tau: f64,
size: [usize; 2],
pixels: Vec<f64>,
mask: Option<Vec<bool>>,
minmax: Option<(f64, f64)>,
},
}
#[cfg(feature = "server")]
impl Payload {
pub fn signal<T, U>(
data: interface::Data<U>,
tau: f64,
idx: Option<usize>,
scale: Option<f64>,
) -> Option<Self>
where
T: Copy,
U: UniqueIdentifier<DataType = Vec<T>>,
f64: From<T>,
{
if let Some(idx) = idx {
data.get(idx).map(|&v| Self::Signal {
tag: <U as interface::Quote>::quote(),
tau,
value: scale.map_or_else(|| v.into(), |s| f64::from(v) * s),
})
} else {
Some(Self::Signals {
tag: <U as interface::Quote>::quote(),
tau,
value: data.iter().map(|v| f64::from(*v)).collect(),
})
}
}
pub fn image<T, U>(
data: interface::Data<U>,
tau: f64,
size: [usize; 2],
minmax: Option<(f64, f64)>,
scale: Option<f64>,
) -> Option<Self>
where
T: Copy,
U: UniqueIdentifier<DataType = Vec<T>>,
f64: From<T>,
{
Some(Self::Image {
tag: <U as interface::Quote>::quote(),
tau,
size,
pixels: Vec::from(data)
.into_iter()
.map(|x| scale.map_or_else(|| x.into(), |s| f64::from(x) * s))
.collect(),
mask: None,
minmax,
})
}
pub fn gmt<T, U>(
data: interface::Data<U>,
tau: f64,
size: [usize; 2],
minmax: Option<(f64, f64)>,
scale: Option<f64>,
) -> Option<Self>
where
T: Copy,
U: UniqueIdentifier<DataType = (Vec<T>, Vec<bool>)>,
f64: From<T>,
{
let (pixels, mask) = std::ops::Deref::deref(&data).clone();
Some(Self::Image {
tag: <U as interface::Quote>::quote(),
tau,
size,
pixels: Vec::from(pixels)
.into_iter()
.map(|x| scale.map_or_else(|| x.into(), |s| f64::from(x) * s))
.collect(),
mask: Some(mask),
minmax,
})
}
}
#[cfg(feature = "client")]
impl Payload {
pub fn max(&self) -> f64 {
match self {
Payload::Image { pixels, .. } => {
*(pixels.iter().max_by(|&a, &b| a.total_cmp(b)).unwrap())
}
_ => unimplemented!("max is implemented only for Payload::Image"),
}
}
pub fn min(&self) -> f64 {
match self {
Payload::Image { pixels, .. } => {
*(pixels.iter().min_by(|&a, &b| a.total_cmp(b)).unwrap())
}
_ => unimplemented!("min is implemented only for Payload::Image"),
}
}
}