use super::{Encode, Error, Type, Writer};
use num_bigint::{BigInt, BigUint, Sign};
impl Encode for BigUint {
const TYPE: &'static Type = &Type::Primitive(-3);
fn write(&self, output: &mut Writer) -> Result<(), Error> {
let count = usize::try_from(self.bits().max(1).div_ceil(7)).map_err(|_| Error::Limit)?;
if count > output.limit.saturating_sub(output.bytes.len()) {
return Err(Error::Limit);
}
write_digits(self.to_radix_le(128), output)
}
}
impl Encode for BigInt {
const TYPE: &'static Type = &Type::Primitive(-4);
fn write(&self, output: &mut Writer) -> Result<(), Error> {
let negative = self.sign() == Sign::Minus;
let lower = usize::try_from(self.bits().saturating_sub(1).max(1).div_ceil(7))
.map_err(|_| Error::Limit)?;
if lower > output.limit.saturating_sub(output.bytes.len()) {
return Err(Error::Limit);
}
let mut digits = if negative {
(self.magnitude() - 1u8).to_radix_le(128)
} else {
self.magnitude().to_radix_le(128)
};
if negative {
for digit in &mut digits {
*digit ^= 127;
}
}
if (digits.last().copied().unwrap_or(0) & 64 != 0) != negative {
digits.push(if negative { 127 } else { 0 });
}
write_digits(digits, output)
}
}
fn write_digits(mut digits: Vec<u8>, output: &mut Writer) -> Result<(), Error> {
if let Some((_, preceding)) = digits.split_last_mut() {
for digit in preceding {
*digit |= 128;
}
}
output.bytes(&digits)
}
#[cfg(test)]
mod tests;