ic-platform 0.31.1

Controlled Candid and IC runtime dependency boundary
Documentation
//! Arbitrary-size integer arithmetic belongs to num-bigint; this module owns
//! only Candid's signed/unsigned LEB128 framing.
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;
        // Preflight a lower bound before materializing a radix conversion.
        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;