use super::sign::trim;
use super::{ByteOrder, Number};
use core::iter::{Product, Sum};
fn small(v: u8) -> Number {
Number::new_from_u8(v, ByteOrder::LittleEndian)
}
fn sum(mut iter: impl Iterator<Item = Number>) -> Number {
let Some(first) = iter.next() else {
return small(0);
};
let mut sum = Number {
value: Vec::new(),
negative: false,
byte_order: first.byte_order,
};
sum += first;
iter.fold(sum, |sum, x| sum + x)
}
fn product(iter: impl Iterator<Item = Number>) -> Number {
let mut stack: Vec<Number> = Vec::new();
for mut x in iter {
while let Some(top) = stack.last()
&& top.value.len() <= x.value.len()
{
let top = stack.pop().unwrap_or_default();
x = top * x;
}
stack.push(x);
}
let Some(mut product) = stack.pop() else {
return small(1);
};
while let Some(below) = stack.pop() {
product = below * product;
}
trim(&mut product);
product
}
impl Sum for Number {
fn sum<I: Iterator<Item = Number>>(iter: I) -> Number {
sum(iter)
}
}
impl<'a> Sum<&'a Number> for Number {
fn sum<I: Iterator<Item = &'a Number>>(mut iter: I) -> Number {
let Some(first) = iter.next() else {
return small(0);
};
let mut sum = Number {
value: Vec::new(),
negative: false,
byte_order: first.byte_order,
};
sum += first;
iter.fold(sum, |sum, x| sum + x)
}
}
impl Product for Number {
fn product<I: Iterator<Item = Number>>(iter: I) -> Number {
product(iter)
}
}
impl<'a> Product<&'a Number> for Number {
fn product<I: Iterator<Item = &'a Number>>(iter: I) -> Number {
product(iter.cloned())
}
}