use std::ops::RangeInclusive;
use context_error::{BasicKind, BoxedError};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::{
parse_json::{ParseJson, use_serde},
system::{e, isize::Charge},
};
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct ChargeRange {
pub start: ChargePoint,
pub end: ChargePoint,
}
impl ChargeRange {
pub fn len(&self, precursor: Charge) -> usize {
(self.end.to_absolute(precursor).value - self.start.to_absolute(precursor).value.max(1))
.unsigned_abs()
}
pub fn charges(&self, precursor: Charge) -> RangeInclusive<Charge> {
Charge::new::<e>(self.start.to_absolute(precursor).value.max(1))
..=self.end.to_absolute(precursor)
}
pub fn charges_iter(
&self,
precursor: Charge,
) -> impl DoubleEndedIterator<Item = Charge> + Clone {
(self.start.to_absolute(precursor).value.max(1)..=self.end.to_absolute(precursor).value)
.map(Charge::new::<e>)
}
pub const ONE: Self = Self {
start: ChargePoint::Absolute(1),
end: ChargePoint::Absolute(1),
};
pub const PRECURSOR: Self = Self {
start: ChargePoint::Relative(0),
end: ChargePoint::Relative(0),
};
pub const ONE_TO_PRECURSOR: Self = Self {
start: ChargePoint::Absolute(1),
end: ChargePoint::Relative(0),
};
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum ChargePoint {
Relative(isize),
Absolute(isize),
}
impl ChargePoint {
fn to_absolute(self, precursor: Charge) -> Charge {
match self {
Self::Absolute(a) => Charge::new::<e>(a),
Self::Relative(r) => Charge::new::<e>(precursor.value + r),
}
}
}
impl ParseJson for ChargeRange {
fn from_json_value(value: Value) -> Result<Self, BoxedError<'static, BasicKind>> {
use_serde(value)
}
}