use num_traits::{pow, One, Zero};
use std::ops::{Add, Div, Mul, RangeInclusive, Sub};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(bound(deserialize = "T: One + Add<Output = T> + Deserialize<'de>"))
)]
pub struct ToRealLE<T> {
#[cfg_attr(feature = "serde", serde(skip))]
to_int: ToIntLE<T>,
start: T,
a: Option<T>,
}
impl<T> ToRealLE<T> {
pub fn new(range: RangeInclusive<T>, len: usize) -> Self
where
T: Copy + One + Add<Output = T> + Sub<Output = T> + Div<Output = T>,
{
let to_int = ToIntLE::new();
let (start, end) = range.into_inner();
Self {
a: if len > 0 {
Some((end - start) / (pow(to_int.two, len) - T::one()))
} else {
None
},
start,
to_int,
}
}
pub fn decode(&self, bits: impl IntoIterator<Item = bool>) -> T
where
T: Copy + Zero + One + Add<Output = T> + Mul<Output = T>,
{
match self.a {
Some(a) => a * self.to_int.decode(bits) + self.start,
None => self.start,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct ToIntLE<T> {
#[cfg_attr(feature = "serde", serde(skip))]
two: T,
}
impl<T> Default for ToIntLE<T>
where
T: One + Add<Output = T>,
{
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "serde")]
impl<'de, T> Deserialize<'de> for ToIntLE<T>
where
T: One + Add<Output = T>,
{
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(Self::new())
}
}
impl<T> ToIntLE<T> {
pub fn new() -> Self
where
T: One + Add<Output = T>,
{
Self {
two: T::one() + T::one(),
}
}
pub fn decode(&self, bits: impl IntoIterator<Item = bool>) -> T
where
T: Copy + Zero + One + Add<Output = T> + Mul<Output = T>,
{
bits.into_iter()
.fold((T::zero(), T::one()), |(acc, a), b| {
(if b { acc + a } else { acc }, self.two * a)
})
.0
}
}