use crate::compile_time_integer::Integer;
use crate::streams::*;
pub struct NoneToError<T, G, E> {
input: G,
from_none: E,
phantom_t: PhantomData<T>,
}
impl<T, G, E> NoneToError<T, G, E> {
pub const fn new(input: G, from_none: E) -> Self {
Self {
input,
from_none,
phantom_t: PhantomData,
}
}
}
impl<T, G, E> Getter<T, E> for NoneToError<T, G, E>
where
G: Getter<T, E>,
E: Clone + Debug,
{
fn get(&self) -> Output<T, E> {
let output = self.input.get()?;
match output {
Some(_) => Ok(output),
None => Err(self.from_none.clone()),
}
}
}
impl<T, G, E> Updatable<E> for NoneToError<T, G, E>
where
G: Updatable<E>,
E: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<E> {
self.input.update()?;
Ok(())
}
}
pub struct NoneToValue<T, G, TG, E> {
input: G,
time_getter: TG,
none_value: T,
phantom_e: PhantomData<E>,
}
impl<T, G, TG, E> NoneToValue<T, G, TG, E> {
pub const fn new(input: G, time_getter: TG, none_value: T) -> Self {
Self {
input,
time_getter,
none_value,
phantom_e: PhantomData,
}
}
}
impl<T, G, TG, E> Getter<T, error::PossibleDoubleError<E>> for NoneToValue<T, G, TG, E>
where
T: Clone,
G: Getter<T, E>,
TG: TimeGetter<E>,
E: Clone + Debug,
{
fn get(&self) -> Output<T, error::PossibleDoubleError<E>> {
let output = match self.input.get() {
Ok(ok) => ok,
Err(err) => return Err(error::PossibleDoubleError::A(err)),
};
match output {
Some(_) => Ok(output),
None => Ok(Some(Datum::new(
match self.time_getter.get() {
Ok(ok) => ok,
Err(err) => return Err(error::PossibleDoubleError::B(err)),
},
self.none_value.clone(),
))),
}
}
}
impl<T, G, TG, E> Updatable<error::PossibleDoubleError<E>> for NoneToValue<T, G, TG, E>
where
G: Updatable<E>,
TG: Updatable<E>,
E: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<error::PossibleDoubleError<E>> {
let side_b = self.time_getter.update();
let side_a = self.input.update();
match (side_a, side_b) {
(Ok(()), Ok(())) => Ok(()),
(Err(a), Ok(())) => Err(error::PossibleDoubleError::A(a)),
(Ok(()), Err(b)) => Err(error::PossibleDoubleError::B(b)),
(Err(a), Err(b)) => Err(error::PossibleDoubleError::AB(a, b)),
}
}
}
pub struct NoneToDefault<T, G, TG, E> {
input: G,
time_getter: TG,
phantom_t: PhantomData<T>,
phantom_e: PhantomData<E>,
}
impl<T, G, TG, E> NoneToDefault<T, G, TG, E> {
pub const fn new(input: G, time_getter: TG) -> Self {
Self {
input,
time_getter,
phantom_t: PhantomData,
phantom_e: PhantomData,
}
}
}
impl<T, G, TG, E> Getter<T, error::PossibleDoubleError<E>> for NoneToDefault<T, G, TG, E>
where
T: Default,
G: Getter<T, E>,
TG: TimeGetter<E>,
E: Clone + Debug,
{
fn get(&self) -> Output<T, error::PossibleDoubleError<E>> {
let input = match self.input.get() {
Ok(option) => option,
Err(error) => return Err(error::PossibleDoubleError::A(error)),
};
if let Some(datum) = input {
return Ok(Some(datum));
}
let time = match self.time_getter.get() {
Ok(time) => time,
Err(error) => return Err(error::PossibleDoubleError::B(error)),
};
Ok(Some(Datum::new(time, T::default())))
}
}
impl<T, G, TG, E> Updatable<error::PossibleDoubleError<E>> for NoneToDefault<T, G, TG, E>
where
G: Updatable<E>,
TG: Updatable<E>,
E: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<error::PossibleDoubleError<E>> {
let side_b = self.time_getter.update();
let side_a = self.input.update();
match (side_a, side_b) {
(Ok(()), Ok(())) => Ok(()),
(Err(a), Ok(())) => Err(error::PossibleDoubleError::A(a)),
(Ok(()), Err(b)) => Err(error::PossibleDoubleError::B(b)),
(Err(a), Err(b)) => Err(error::PossibleDoubleError::AB(a, b)),
}
}
}
pub use acceleration_to_state::*;
mod acceleration_to_state {
use super::*;
struct Update0<P, V, A> {
last_update_time: Time,
acceleration: A,
update_1: Option<Update1<P, V>>,
}
struct Update1<P, V> {
velocity: V,
update_2_position: Option<P>,
}
pub struct AccelerationToState<G, S: GenericState> {
input: G,
update_0: Option<Update0<S::Position, S::Velocity, S::Acceleration>>,
}
impl<G, S: GenericState> AccelerationToState<G, S> {
pub const fn new(input: G) -> Self {
Self {
input,
update_0: None,
}
}
}
impl<G, S: GenericState, E: Clone + Debug> Getter<S, E> for AccelerationToState<G, S>
where
Self: Updatable<E>,
{
fn get(&self) -> Output<S, E> {
if let Some(update_0) = &self.update_0
&& let Some(update_1) = &update_0.update_1
&& let Some(update_2_position) = update_1.update_2_position
{
return Ok(Some(Datum::new(
update_0.last_update_time,
S::generic_new(update_2_position, update_1.velocity, update_0.acceleration),
)));
}
Ok(None)
}
}
impl<G: Getter<S::Acceleration, E>, S: GenericState, E: Clone + Debug> Updatable<E>
for AccelerationToState<G, S>
{
fn update(&mut self) -> NothingOrError<E> {
self.input.update()?;
match self.input.get() {
Ok(Some(new_acceleration_datum)) => {
let new_update_time = new_acceleration_datum.time;
let new_acceleration = new_acceleration_datum.value;
self.update_0 = Some(Update0 {
last_update_time: new_update_time,
acceleration: new_acceleration,
update_1: if let Some(update_0) = &self.update_0 {
let old_update_time = update_0.last_update_time;
let old_acceleration = update_0.acceleration;
let delta_time = new_update_time - old_update_time;
let added_velocity = (old_acceleration + new_acceleration)
* Dimensionless::new(0.5)
* delta_time;
Some(if let Some(update_1) = &update_0.update_1 {
let old_velocity = update_1.velocity;
let new_velocity = old_velocity + added_velocity;
let added_position = (old_velocity + new_velocity)
* Dimensionless::new(0.5)
* delta_time;
Update1 {
velocity: new_velocity,
update_2_position: Some(
if let Some(old_position) = update_1.update_2_position {
old_position + added_position
} else {
added_position
},
),
}
} else {
Update1 {
velocity: added_velocity,
update_2_position: None,
}
})
} else {
None
},
});
}
Ok(None) => {}
Err(error) => {
self.update_0 = None;
return Err(error);
}
}
Ok(())
}
}
}
pub use velocity_to_state::*;
mod velocity_to_state {
use super::*;
struct Update0<P, V, A> {
last_update_time: Time,
velocity: V,
update_1: Option<Update1<P, A>>,
}
struct Update1<P, A> {
position: P,
acceleration: A,
}
pub struct VelocityToState<G, S: GenericState> {
input: G,
update_0: Option<Update0<S::Position, S::Velocity, S::Acceleration>>,
}
impl<G, S: GenericState> VelocityToState<G, S> {
pub const fn new(input: G) -> Self {
Self {
input,
update_0: None,
}
}
}
impl<G, S: GenericState, E: Clone + Debug> Getter<S, E> for VelocityToState<G, S>
where
Self: Updatable<E>,
{
fn get(&self) -> Output<S, E> {
if let Some(update_0) = &self.update_0
&& let Some(update_1) = &update_0.update_1
{
return Ok(Some(Datum::new(
update_0.last_update_time,
S::generic_new(update_1.position, update_0.velocity, update_1.acceleration),
)));
}
Ok(None)
}
}
impl<G: Getter<S::Velocity, E>, S: GenericState, E: Clone + Debug> Updatable<E>
for VelocityToState<G, S>
{
fn update(&mut self) -> NothingOrError<E> {
self.input.update()?;
match self.input.get() {
Ok(Some(new_velocity_datum)) => {
let new_update_time = new_velocity_datum.time;
let new_velocity = new_velocity_datum.value;
self.update_0 = Some(Update0 {
last_update_time: new_update_time,
velocity: new_velocity,
update_1: if let Some(update_0) = &self.update_0 {
let old_update_time = update_0.last_update_time;
let old_velocity = update_0.velocity;
let delta_time = new_update_time - old_update_time;
let new_acceleration = (new_velocity - old_velocity) / delta_time;
let added_position = (old_velocity + new_velocity)
* Dimensionless::new(0.5)
* delta_time;
Some(Update1 {
position: if let Some(update_1) = &update_0.update_1 {
update_1.position + added_position
} else {
added_position
},
acceleration: new_acceleration,
})
} else {
None
},
})
}
Ok(None) => {}
Err(error) => {
self.update_0 = None;
return Err(error);
}
}
Ok(())
}
}
}
pub use position_to_state::*;
mod position_to_state {
use super::*;
struct Update0<P, V, A> {
last_update_time: Time,
position: P,
update_1: Option<Update1<V, A>>,
}
struct Update1<V, A> {
velocity: V,
update_2_acceleration: Option<A>,
}
pub struct PositionToState<G, S: GenericState> {
input: G,
update_0: Option<Update0<S::Position, S::Velocity, S::Acceleration>>,
}
impl<G, S: GenericState> PositionToState<G, S> {
pub const fn new(input: G) -> Self {
Self {
input,
update_0: None,
}
}
}
impl<G, S: GenericState, E: Clone + Debug> Getter<S, E> for PositionToState<G, S>
where
Self: Updatable<E>,
{
fn get(&self) -> Output<S, E> {
if let Some(update_0) = &self.update_0
&& let Some(update_1) = &update_0.update_1
&& let Some(update_2_acceleration) = update_1.update_2_acceleration
{
return Ok(Some(Datum::new(
update_0.last_update_time,
S::generic_new(update_0.position, update_1.velocity, update_2_acceleration),
)));
}
Ok(None)
}
}
impl<G: Getter<S::Position, E>, S: GenericState, E: Clone + Debug> Updatable<E>
for PositionToState<G, S>
{
fn update(&mut self) -> NothingOrError<E> {
self.input.update()?;
match self.input.get() {
Ok(Some(new_position_datum)) => {
let new_update_time = new_position_datum.time;
let new_position = new_position_datum.value;
self.update_0 = Some(Update0 {
last_update_time: new_update_time,
position: new_position,
update_1: if let Some(update_0) = &self.update_0 {
let old_update_time = update_0.last_update_time;
let old_position = update_0.position;
let delta_time = new_update_time - old_update_time;
let new_velocity = (new_position - old_position) / delta_time;
Some(Update1 {
velocity: new_velocity,
update_2_acceleration: if let Some(update_1) = &update_0.update_1 {
let old_velocity = update_1.velocity;
let new_acceleration =
(new_velocity - old_velocity) / delta_time;
Some(new_acceleration)
} else {
None
},
})
} else {
None
},
});
}
Ok(None) => {}
Err(error) => {
self.update_0 = None;
return Err(error);
}
}
Ok(())
}
}
}
pub struct DimensionAdder<MM, S, G> {
input: G,
phantom_mm: PhantomData<MM>,
phantom_s: PhantomData<S>,
}
impl<MM, S, G> DimensionAdder<MM, S, G> {
pub const fn new(input: G) -> Self {
Self {
input,
phantom_mm: PhantomData,
phantom_s: PhantomData,
}
}
}
impl<T, MM, S, G, E> Getter<Quantity<T, MM, S>, E> for DimensionAdder<MM, S, G>
where
MM: Integer,
S: Integer,
G: Getter<T, E>,
E: Clone + Debug,
{
fn get(&self) -> Output<Quantity<T, MM, S>, E> {
self.input
.get()
.map_ok_some_value(|value| Quantity::new(value))
}
}
impl<MM, S, G, E> Updatable<E> for DimensionAdder<MM, S, G>
where
G: Updatable<E>,
E: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<E> {
self.input.update()?;
Ok(())
}
}
pub struct DimensionRemover<MM, S, G> {
input: G,
phantom_mm: PhantomData<MM>,
phantom_s: PhantomData<S>,
}
impl<MM: Integer, S: Integer, G> DimensionRemover<MM, S, G> {
pub const fn new(input: G) -> Self {
Self {
input,
phantom_mm: PhantomData,
phantom_s: PhantomData,
}
}
}
impl<T, MM, S, G, E> Getter<T, E> for DimensionRemover<MM, S, G>
where
MM: Integer,
S: Integer,
G: Getter<Quantity<T, MM, S>, E>,
E: Clone + Debug,
{
fn get(&self) -> Output<T, E> {
self.input
.get()
.map_ok_some_value(|quantity| quantity.into_inner())
}
}
impl<MM, S, G: Updatable<E>, E: Clone + Debug> Updatable<E> for DimensionRemover<MM, S, G> {
fn update(&mut self) -> NothingOrError<E> {
self.input.update()?;
Ok(())
}
}
pub struct IntoConverter<TI, G> {
input: G,
phantom_ti: PhantomData<TI>,
}
impl<TI, G> IntoConverter<TI, G> {
pub const fn new(input: G) -> Self {
Self {
input,
phantom_ti: PhantomData,
}
}
}
impl<TI, TO, G, E> Getter<TO, E> for IntoConverter<TI, G>
where
TI: Into<TO>,
G: Getter<TI, E>,
E: Clone + Debug,
{
fn get(&self) -> Output<TO, E> {
self.input.get().map_ok_some_value(|value| value.into())
}
}
impl<TI, G: Updatable<E>, E: Clone + Debug> Updatable<E> for IntoConverter<TI, G> {
fn update(&mut self) -> NothingOrError<E> {
self.input.update()?;
Ok(())
}
}
pub struct ErrorIntoConverter<G, EI> {
input: G,
phantom_ei: PhantomData<EI>,
}
impl<G, EI> ErrorIntoConverter<G, EI> {
pub const fn new(input: G) -> Self {
Self {
input,
phantom_ei: PhantomData,
}
}
}
impl<T, G, EI, EO> Getter<T, EO> for ErrorIntoConverter<G, EI>
where
G: Getter<T, EI>,
EI: Clone + Debug + Into<EO>,
EO: Clone + Debug,
{
fn get(&self) -> Output<T, EO> {
self.input.get().map_err(|error| error.into())
}
}
impl<G, EI, EO> Updatable<EO> for ErrorIntoConverter<G, EI>
where
G: Updatable<EI>,
EI: Clone + Debug + Into<EO>,
EO: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<EO> {
self.input.update().map_err(|error| error.into())?;
Ok(())
}
}
macro_rules! prioritize_stream {
($name: ident, $operation: ident, $doc: literal) => {
#[doc = $doc]
pub struct $name<G> {
input: G,
}
impl<G> $name<G> {
#[doc = "Constructor for `"]
#[doc = stringify!($name)]
#[doc = "`."]
#[inline]
pub const fn new(input: G) -> Self {
Self { input }
}
}
impl<G: Updatable<error::PossibleDoubleError<E>>, E: Clone + Debug> Updatable<E>
for $name<G>
{
fn update(&mut self) -> NothingOrError<E> {
self.input
.update()
.map_err(|possible_double_error| possible_double_error.$operation())
}
}
impl<T, G: Getter<T, error::PossibleDoubleError<E>>, E: Clone + Debug> Getter<T, E>
for $name<G>
{
fn get(&self) -> Output<T, E> {
self.input
.get()
.map_err(|possible_double_error| possible_double_error.$operation())
}
}
impl<T, G: Settable<T, error::PossibleDoubleError<E>>, E: Clone + Debug> Settable<T, E>
for $name<G>
{
fn set(&mut self, value: T) -> NothingOrError<E> {
self.input
.set(value)
.map_err(|possible_double_error| possible_double_error.$operation())
}
}
};
}
prioritize_stream!(
PrioritizeA,
prioritize_a,
"Collapses `Err` variants of [`error::PossibleDoubleError`] returned by its input's `Getter`, `Settable`, and `Updatable` implementations into a single error value, keeping the Side A error if both sides have errored.\n\nThis uses [`error::PossibleDoubleError::prioritize_a`] internally."
);
prioritize_stream!(
PrioritizeB,
prioritize_b,
"Collapses `Err` variants of [`error::PossibleDoubleError`] returned by its input's `Getter`, `Settable`, and `Updatable` implementations into a single error value, keeping the Side B error if both sides have errored.\n\nThis uses [`error::PossibleDoubleError::prioritize_b`] internally."
);