feat(core): add more fine grain casting operations for signals

This commit is contained in:
Anand Balakrishnan 2023-04-16 17:14:57 -07:00
parent 4431b79bcd
commit aa952c3151
No known key found for this signature in database
3 changed files with 77 additions and 41 deletions

View file

@ -29,6 +29,9 @@ pub enum Error {
#[error("incorrect signal type")] #[error("incorrect signal type")]
InvalidSignalType, InvalidSignalType,
#[error("invalid cast from {from} to {to}")]
InvalidCast { from: &'static str, to: &'static str },
} }
pub type ArgusError = Error; pub type ArgusError = Error;

View file

@ -1,11 +1,14 @@
use core::iter::zip; use core::iter::zip;
use crate::signals::traits::SignalNumCast; use crate::signals::traits::{SignalNumCast, TrySignalCast};
use crate::signals::Signal; use crate::signals::Signal;
use crate::{ArgusError, ArgusResult};
macro_rules! impl_cast { macro_rules! impl_cast_bool {
(bool => $to:ty) => { ([$( $to:ty ),*]) => {
paste::paste! { paste::paste! {
impl SignalNumCast for Signal<bool> {
$(
#[inline] #[inline]
fn [<to_ $to>](&self) -> Option<Signal<$to>> { fn [<to_ $to>](&self) -> Option<Signal<$to>> {
match self { match self {
@ -21,10 +24,31 @@ macro_rules! impl_cast {
} }
} }
} }
)*
}
$(
impl TrySignalCast<Signal<$to>> for Signal<bool> {
fn try_cast(&self) -> ArgusResult<Signal<$to>> {
self.[<to_ $to>]().ok_or(ArgusError::InvalidCast {
from: std::any::type_name::<bool>(),
to: std::any::type_name::<$to>(),
})
}
}
)*
} }
}; };
($from:ty => $to:ty) => { () => {
impl_cast_bool!([i8, i16, i32, i64, u8, u16, u32, u64, f32, f64]);
};
}
macro_rules! impl_cast {
($from:ty, [$( $to:ty ),*]) => {
paste::paste! { paste::paste! {
impl SignalNumCast for Signal<$from> {
$(
#[inline] #[inline]
fn [<to_ $to>](&self) -> Option<Signal<$to>> { fn [<to_ $to>](&self) -> Option<Signal<$to>> {
match self { match self {
@ -40,25 +64,28 @@ macro_rules! impl_cast {
} }
} }
} }
)*
}
$(
impl TrySignalCast<Signal<$to>> for Signal<$from> {
fn try_cast(&self) -> ArgusResult<Signal<$to>> {
self.[<to_ $to>]().ok_or(ArgusError::InvalidCast {
from: std::any::type_name::<$from>(),
to: std::any::type_name::<$to>(),
})
}
}
)*
} }
}; };
($from:ty) => { ($from:ty) => {
impl SignalNumCast for Signal<$from> { impl_cast!($from, [i8, i16, i32, i64, u8, u16, u32, u64, f32, f64]);
impl_cast!($from => i8);
impl_cast!($from => i16);
impl_cast!($from => i32);
impl_cast!($from => i64);
impl_cast!($from => u8);
impl_cast!($from => u16);
impl_cast!($from => u32);
impl_cast!($from => u64);
impl_cast!($from => f32);
impl_cast!($from => f64);
}
}; };
} }
impl_cast_bool!();
impl_cast!(i8); impl_cast!(i8);
impl_cast!(i16); impl_cast!(i16);
impl_cast!(i32); impl_cast!(i32);

View file

@ -4,6 +4,7 @@ use std::time::Duration;
use paste::paste; use paste::paste;
use super::{Sample, Signal}; use super::{Sample, Signal};
use crate::ArgusResult;
/// Trait for values that are linear interpolatable /// Trait for values that are linear interpolatable
pub trait LinearInterpolatable { pub trait LinearInterpolatable {
@ -113,7 +114,7 @@ pub trait SignalMinMax<Rhs = Self> {
fn max(&self, rhs: &Rhs) -> Self::Output; fn max(&self, rhs: &Rhs) -> Self::Output;
} }
/// Trait for converting between numeric signal types /// Trait for converting between signal types
pub trait SignalNumCast { pub trait SignalNumCast {
fn to_i8(&self) -> Option<Signal<i8>>; fn to_i8(&self) -> Option<Signal<i8>>;
fn to_i16(&self) -> Option<Signal<i16>>; fn to_i16(&self) -> Option<Signal<i16>>;
@ -127,6 +128,11 @@ pub trait SignalNumCast {
fn to_f64(&self) -> Option<Signal<f64>>; fn to_f64(&self) -> Option<Signal<f64>>;
} }
/// Trait to cast signal onto some type
pub trait TrySignalCast<T>: Sized + SignalNumCast {
fn try_cast(&self) -> ArgusResult<T>;
}
/// Trait for computing the absolute value of the samples in a signal /// Trait for computing the absolute value of the samples in a signal
pub trait SignalAbs { pub trait SignalAbs {
fn abs(&self) -> Self; fn abs(&self) -> Self;