use std::convert::Infallible;
use derive_where::derive_where;
use num_complex::Complex64;
use crate::waveform::{higher_kinded, sampling::IqSamples, Concrete, Partial, WaveformData};
use super::IqSamplesOrPlaceholder;
pub(super) trait Sampleable: WaveformData<Real: Copy, Complex: Copy> {
type IsPartial: Copy + Eq + std::fmt::Debug;
fn eval_real(real: Self::Real) -> Result<f64, Self::IsPartial>;
}
impl Sampleable for Partial<Concrete> {
type IsPartial = ();
#[inline(always)]
fn eval_real(real: Self::Real) -> Result<f64, Self::IsPartial> {
real.ok_or(())
}
}
impl Sampleable for Concrete {
type IsPartial = Infallible;
#[inline(always)]
fn eval_real(real: Self::Real) -> Result<f64, Self::IsPartial> {
Ok(real)
}
}
pub(super) trait ConcretizableWaveform:
higher_kinded::WaveformParameters<WaveformData: Sampleable> + Copy
{
fn concretize(
self,
) -> Result<Self::WithWaveformData<Concrete>, <Self::WaveformData as Sampleable>::IsPartial>;
}
pub(super) trait ConcretizableFromTo<T: Sampleable, C>:
ConcretizableWaveform<WaveformData = T, WithWaveformData<Concrete> = C>
{
}
impl<
T: Sampleable,
C,
W: ConcretizableWaveform<WaveformData = T, WithWaveformData<Concrete> = C>,
> ConcretizableFromTo<T, C> for W
{
}
#[derive_where(Clone, Copy, PartialEq, Eq, Debug; P, T)]
pub(super) enum Value<S: Sampleable, P, T> {
Partial(S::IsPartial, P),
Total(T),
}
pub(super) type IqSamplesFor<S> = Value<S, IqSamples<()>, IqSamples<Complex64>>;
impl<S: Sampleable<IsPartial = Infallible>, P, T> Value<S, P, T> {
pub(super) fn unwrap_total(self) -> T {
match self {
Self::Partial(never, _) => match never {},
Self::Total(total) => total,
}
}
}
impl IqSamplesFor<Partial<Concrete>> {
pub(super) fn into_iq_samples_or_placeholder(self) -> IqSamplesOrPlaceholder {
match self {
Self::Partial((), placeholder) => IqSamplesOrPlaceholder::Placeholder(placeholder),
Self::Total(samples) => IqSamplesOrPlaceholder::Samples(samples),
}
}
}