use std::io::Write;
use bytes::{Buf, BufMut};
use crate::{
coefficient::{
Coefficient, CoefficientView, SerializedFloat, SerializedLargeRational, SerializedRational,
SerializedRationalPolynomial,
},
domains::{
backend::integer::{from_lsf_bytes, lsf_byte_size, write_lsf_bytes},
finite_field::FiniteFieldElement,
integer::{Integer, IntegerRing, Z},
rational::Fraction,
rational_polynomial::RationalPolynomial,
},
state::{FiniteFieldIndex, State, VariableListIndex},
};
const U8_NUM: u8 = 0b00000001;
const U16_NUM: u8 = 0b00000010;
const U32_NUM: u8 = 0b00000011;
const U64_NUM: u8 = 0b00000100;
const FIN_NUM: u8 = 0b00000101;
const ARB_NUM: u8 = 0b00000111;
const RAT_POLY: u8 = 0b00001000;
const FLOAT: u8 = 0b00001001;
const COMPLEX: u8 = 0b00001010;
const INDETERMINATE: u8 = 0b00001100;
const COMPLEX_INFINITY: u8 = 0b00001101;
const DIRECTED_INFINITY: u8 = 0b00001111;
const U8_DEN: u8 = 0b00010000;
const U16_DEN: u8 = 0b00100000;
const U32_DEN: u8 = 0b00110000;
const U64_DEN: u8 = 0b01000000;
const ARB_DEN: u8 = 0b01110000;
const NUM_MASK: u8 = 0b00001111;
const DEN_MASK: u8 = 0b01110000;
const SIGN: u8 = 0b10000000;
const U8_NUM_U8_DEN: u8 = U8_NUM | U8_DEN;
const U16_NUM_U8_DEN: u8 = U16_NUM | U8_DEN;
const U32_NUM_U8_DEN: u8 = U32_NUM | U8_DEN;
const U64_NUM_U8_DEN: u8 = U64_NUM | U8_DEN;
const U8_NUM_U16_DEN: u8 = U8_NUM | U16_DEN;
const U16_NUM_U16_DEN: u8 = U16_NUM | U16_DEN;
const U32_NUM_U16_DEN: u8 = U32_NUM | U16_DEN;
const U64_NUM_U16_DEN: u8 = U64_NUM | U16_DEN;
const U8_NUM_U32_DEN: u8 = U8_NUM | U32_DEN;
const U16_NUM_U32_DEN: u8 = U16_NUM | U32_DEN;
const U32_NUM_U32_DEN: u8 = U32_NUM | U32_DEN;
const U64_NUM_U32_DEN: u8 = U64_NUM | U32_DEN;
const U8_NUM_U64_DEN: u8 = U8_NUM | U64_DEN;
const U16_NUM_U64_DEN: u8 = U16_NUM | U64_DEN;
const U32_NUM_U64_DEN: u8 = U32_NUM | U64_DEN;
const U64_NUM_U64_DEN: u8 = U64_NUM | U64_DEN;
const SKIP_TABLE: [u8; (NUM_MASK | DEN_MASK) as usize + 1] = {
let mut dest = [0u8; (NUM_MASK | DEN_MASK) as usize + 1];
dest[U8_NUM as usize] = 1;
dest[U16_NUM as usize] = 2;
dest[U8_NUM_U8_DEN as usize] = 2;
dest[U16_NUM_U8_DEN as usize] = 3;
dest[U8_NUM_U16_DEN as usize] = 3;
dest[U32_NUM as usize] = 4;
dest[U16_NUM_U16_DEN as usize] = 4;
dest[U32_NUM_U8_DEN as usize] = 5;
dest[U8_NUM_U32_DEN as usize] = 5;
dest[U32_NUM_U16_DEN as usize] = 6;
dest[U16_NUM_U32_DEN as usize] = 6;
dest[U64_NUM as usize] = 8;
dest[U32_NUM_U32_DEN as usize] = 8;
dest[U64_NUM_U8_DEN as usize] = 9;
dest[U8_NUM_U64_DEN as usize] = 9;
dest[U64_NUM_U16_DEN as usize] = 10;
dest[U16_NUM_U64_DEN as usize] = 10;
dest[U64_NUM_U32_DEN as usize] = 12;
dest[U32_NUM_U64_DEN as usize] = 12;
dest[U64_NUM_U64_DEN as usize] = 16;
dest
};
#[inline(always)]
const fn get_size_of_natural(num_type: u8) -> u8 {
match num_type {
0 => 0,
U8_NUM => 1,
U16_NUM => 2,
U32_NUM => 4,
U64_NUM => 8,
_ => unreachable!(),
}
}
impl SerializedRationalPolynomial<'_> {
pub fn deserialize(self) -> RationalPolynomial<IntegerRing, u16> {
let mut source = self.0;
let index;
let num_nterms;
let den_nterms;
(index, num_nterms, source) = source.get_frac_u64();
(den_nterms, _, source) = source.get_frac_u64();
let vars = State::get_variable_list(VariableListIndex(index as usize));
let nvars = vars.len();
let mut poly = RationalPolynomial::new(&Z, vars);
poly.numerator.exponents = vec![0u16; num_nterms as usize * nvars];
for i in 0..poly.numerator.exponents.len() {
poly.numerator.exponents[i] = source.get_u16_le();
}
poly.denominator.exponents = vec![0u16; den_nterms as usize * nvars];
for i in 0..poly.denominator.exponents.len() {
poly.denominator.exponents[i] = source.get_u16_le();
}
fn parse_num(source: &mut &[u8]) -> Integer {
match source.get_u8() {
1 => Integer::Single(source.get_i64_le()),
2 => Integer::Double(source.get_i128_le()),
x @ 4 | x @ 5 => {
let (num_digits, _, new_source) = source.get_frac_u64();
*source = new_source;
let i = from_lsf_bytes(&source[..num_digits as usize]);
source.advance(num_digits as usize);
if x == 5 {
Integer::from(-i)
} else {
Integer::from(i)
}
}
_ => unreachable!(),
}
}
for _ in 0..num_nterms {
poly.numerator.coefficients.push(parse_num(&mut source));
}
poly.denominator.coefficients.clear();
for _ in 0..den_nterms {
poly.denominator.coefficients.push(parse_num(&mut source));
}
poly
}
}
pub trait PackedRationalNumberWriter {
fn write_packed(&self, dest: &mut Vec<u8>);
fn write_packed_fixed(&self, dest: &mut [u8]);
fn get_packed_size(&self) -> u64;
}
impl PackedRationalNumberWriter for Coefficient {
fn write_packed(&self, dest: &mut Vec<u8>) {
#[inline(always)]
fn write_rational(r: &Fraction<IntegerRing>, dest: &mut Vec<u8>) {
match (r.numerator_ref(), r.denominator_ref()) {
(Integer::Single(num), Integer::Single(den)) => {
(*num, *den as u64).write_packed(dest)
}
_ => {
write_multi_rational(r, dest);
}
}
}
#[inline(always)]
fn write_multi_rational(r: &Fraction<IntegerRing>, dest: &mut Vec<u8>) {
let num = r.numerator_ref().clone().to_multi_prec();
let den = r.denominator_ref().clone().to_multi_prec();
let num_digits = lsf_byte_size(&num);
let den_digits = lsf_byte_size(&den);
dest.put_u8(ARB_NUM | ARB_DEN);
if r.numerator_ref().is_negative() {
(-(num_digits as i64), den_digits as u64).write_packed(dest);
} else {
(num_digits as i64, den_digits as u64).write_packed(dest);
}
write_lsf_bytes(&num, dest);
write_lsf_bytes(&den, dest);
}
match self {
Coefficient::Complex(c) => {
if c.im.is_zero() {
write_rational(&c.re, dest);
} else {
dest.put_u8(COMPLEX);
write_rational(&c.re, dest);
write_rational(&c.im, dest);
}
}
Coefficient::Indeterminate => {
dest.put_u8(INDETERMINATE);
}
Coefficient::Infinity(None) => {
dest.put_u8(COMPLEX_INFINITY);
}
Coefficient::Infinity(Some(dir)) => {
dest.put_u8(DIRECTED_INFINITY);
write_multi_rational(&dir.re, dest);
write_multi_rational(&dir.im, dest);
}
Coefficient::Float(f) => {
dest.put_u8(FLOAT);
let s = f.re.serialize();
dest.put_u64_le(s.len() as u64 + 4);
dest.put_u32_le(f.re.prec());
dest.write_all(&s).unwrap();
let s = f.im.serialize();
dest.put_u64_le(s.len() as u64 + 4);
dest.put_u32_le(f.im.prec());
dest.write_all(&s).unwrap();
}
Coefficient::FiniteField(num, f) => {
dest.put_u8(FIN_NUM);
(*num.inner(), f.0 as u64).write_packed(dest); }
Coefficient::RationalPolynomial(p) => {
dest.put_u8(RAT_POLY);
dest.put_u32(0);
let pos = dest.len();
let index = State::get_or_insert_variable_list(p.get_variables().clone());
(index.0 as u64, p.numerator.nterms() as u64).write_packed(dest);
(p.denominator.nterms() as u64, 1).write_packed(dest);
for i in p.numerator.exponents.iter().chain(&p.denominator.exponents) {
dest.put_u16_le(*i);
}
for i in p
.numerator
.coefficients
.iter()
.chain(&p.denominator.coefficients)
{
match i {
Integer::Single(n) => {
dest.put_u8(1);
dest.put_i64_le(*n);
}
Integer::Double(d) => {
dest.put_u8(2);
dest.put_i128_le(*d);
}
Integer::Large(l) => {
if l.is_negative() {
dest.put_u8(5);
} else {
dest.put_u8(4);
}
let num_digits = lsf_byte_size(l);
(num_digits as u64, 1).write_packed(dest);
write_lsf_bytes(l, dest);
}
}
}
let len = dest.len() - pos;
if len > u32::MAX as usize {
panic!("Rational polynomial too large to serialize");
}
dest[pos - 4..pos].copy_from_slice(&(len as u32).to_le_bytes());
}
}
}
fn write_packed_fixed(&self, mut dest: &mut [u8]) {
match self {
Coefficient::Complex(c) => {
let real = c.im.is_zero();
if !real {
dest.put_u8(COMPLEX);
}
match (c.re.numerator_ref(), c.re.denominator_ref()) {
(Integer::Single(num), Integer::Single(den)) => {
(*num, *den as u64).write_packed_fixed(dest);
}
_ => todo!("Writing large packed rational not implemented"),
}
if !real {
match (c.im.numerator_ref(), c.im.denominator_ref()) {
(Integer::Single(num), Integer::Single(den)) => {
(*num, *den as u64).write_packed_fixed(dest);
}
_ => todo!("Writing large packed rational not implemented"),
}
}
}
Coefficient::Indeterminate => {
dest.put_u8(INDETERMINATE);
}
Coefficient::Infinity(None) => {
dest.put_u8(COMPLEX_INFINITY);
}
Coefficient::Infinity(Some(_)) => {
dest.put_u8(DIRECTED_INFINITY);
todo!("Writing large packed rational not implemented");
}
Coefficient::Float(_) => todo!("Writing packed float not implemented"),
Coefficient::RationalPolynomial(_) => {
todo!("Writing packed rational polynomial not implemented")
}
Coefficient::FiniteField(num, f) => {
dest.put_u8(FIN_NUM);
(*num.inner(), f.0 as u64).write_packed_fixed(dest);
}
}
}
fn get_packed_size(&self) -> u64 {
#[inline(always)]
fn packed_size_rat(r: &Fraction<IntegerRing>) -> u64 {
match (r.numerator_ref(), r.denominator_ref()) {
(Integer::Single(num), Integer::Single(den)) => {
(*num, *den as u64).get_packed_size()
}
_ => packed_size_multi_rat(r),
}
}
#[inline(always)]
fn packed_size_multi_rat(r: &Fraction<IntegerRing>) -> u64 {
let n = lsf_byte_size(&r.numerator_ref().clone().to_multi_prec()) as u64;
let d = lsf_byte_size(&r.denominator_ref().clone().to_multi_prec()) as u64;
1 + (n, d).get_packed_size() + n + d
}
match self {
Coefficient::Complex(c) => {
if c.im.is_zero() {
packed_size_rat(&c.re)
} else {
1 + packed_size_rat(&c.re) + packed_size_rat(&c.im)
}
}
Coefficient::Indeterminate => 1,
Coefficient::Infinity(None) => 1,
Coefficient::Infinity(Some(c)) => {
1 + packed_size_multi_rat(&c.re) + packed_size_multi_rat(&c.im)
}
Coefficient::Float(f) => {
let s = f.re.serialize();
let si = f.im.serialize();
1 + 8 + 4 + s.len() as u64 + 8 + 4 + si.len() as u64
}
Coefficient::FiniteField(m, i) => 2 + (*m.inner(), i.0 as u64).get_packed_size(),
Coefficient::RationalPolynomial(_) => {
unimplemented!("Cannot get the packed size of a rational polynomial")
}
}
}
}
pub trait PackedRationalNumberReader {
fn get_coeff_view(&self) -> (CoefficientView<'_>, &[u8]);
fn get_frac_u64(&self) -> (u64, u64, &[u8]);
fn get_frac_i64(&self) -> (i64, u64, &[u8]);
fn skip_rational(&self) -> &[u8];
fn is_small_int(&self) -> bool;
fn is_zero_rat(&self) -> bool;
fn is_one_rat(&self) -> bool;
}
impl PackedRationalNumberReader for [u8] {
#[inline(always)]
fn get_coeff_view(&self) -> (CoefficientView<'_>, &[u8]) {
let mut source = self;
let disc = source.get_u8();
if disc == RAT_POLY {
let len = source.get_u32_le() as usize;
let start = source;
source.advance(len);
(
CoefficientView::RationalPolynomial(SerializedRationalPolynomial(&start[..len])),
source,
)
} else if disc == FLOAT {
let len = source.get_u64_le() as usize;
let start = source;
source.advance(len);
let len_i = source.get_u64_le() as usize;
let start2 = source;
source.advance(len_i);
(
CoefficientView::Float(
SerializedFloat(&start[..len]),
SerializedFloat(&start2[..len_i]),
),
source,
)
} else if disc == COMPLEX {
let (num, r) = source.get_coeff_view();
let (den, r) = r.get_coeff_view();
if let CoefficientView::Natural(n, d, _, _) = num {
if let CoefficientView::Natural(ni, di, _, _) = den {
(CoefficientView::Natural(n, d, ni, di), r)
} else if let CoefficientView::Large(ri, _) = den {
(
CoefficientView::Large(SerializedRational::Natural(n, d), ri),
r,
)
} else {
unreachable!()
}
} else if let CoefficientView::Large(rn, _) = num {
if let CoefficientView::Natural(ni, di, _, _) = den {
(
CoefficientView::Large(rn, SerializedRational::Natural(ni, di)),
r,
)
} else if let CoefficientView::Large(ri, _) = den {
(CoefficientView::Large(rn, ri), r)
} else {
unreachable!()
}
} else {
unreachable!()
}
} else if disc == INDETERMINATE {
(CoefficientView::Indeterminate, source)
} else if disc == COMPLEX_INFINITY {
(CoefficientView::Infinity(None), source)
} else if disc == DIRECTED_INFINITY {
let (num, r) = source.get_coeff_view();
let (den, r) = r.get_coeff_view();
if let CoefficientView::Large(rn, _) = num {
if let CoefficientView::Large(ri, _) = den {
(CoefficientView::Infinity(Some((rn, ri))), r)
} else {
unreachable!()
}
} else {
unreachable!()
}
} else if (disc & NUM_MASK) == ARB_NUM {
let is_negative = unsafe { source.get_unchecked(0) & SIGN != 0 };
let (num, den);
(num, den, source) = source.get_frac_u64();
let num_len = num as usize;
let den_len = den as usize;
let num_limbs = &source[..num_len];
let den_limbs = &source[num_len..num_len + den_len];
(
CoefficientView::Large(
SerializedRational::Large(SerializedLargeRational {
is_negative,
num_digits: num_limbs,
den_digits: den_limbs,
}),
SerializedRational::Large(SerializedLargeRational {
is_negative: false,
num_digits: &[],
den_digits: &[],
}),
),
&source[num_len + den_len..],
)
} else if (disc & NUM_MASK) == FIN_NUM {
let (num, fi);
(num, fi, source) = source.get_frac_u64();
(
CoefficientView::FiniteField(
FiniteFieldElement::from_inner(num),
FiniteFieldIndex(fi as usize),
),
source,
)
} else {
let (num, den, source) = self.get_frac_i64();
(CoefficientView::Natural(num, den as i64, 0, 1), source)
}
}
#[inline(always)]
fn get_frac_u64(&self) -> (u64, u64, &[u8]) {
let mut source = self;
let disc = source.get_u8();
match disc & (NUM_MASK | DEN_MASK) {
U8_NUM => {
let n = source.get_u8();
(n as u64, 1, source)
}
U16_NUM => {
let n = source.get_u16_le();
(n as u64, 1, source)
}
U32_NUM => {
let n = source.get_u32_le();
(n as u64, 1, source)
}
U64_NUM => {
let n = source.get_u64_le();
(n, 1, source)
}
U8_NUM_U8_DEN => {
let n = source.get_u8();
let d = source.get_u8();
(n as u64, d as u64, source)
}
U16_NUM_U8_DEN => {
let n = source.get_u16_le();
let d = source.get_u8();
(n as u64, d as u64, source)
}
U32_NUM_U8_DEN => {
let n = source.get_u32_le();
let d = source.get_u8();
(n as u64, d as u64, source)
}
U64_NUM_U8_DEN => {
let n = source.get_u64_le();
let d = source.get_u8();
(n, d as u64, source)
}
U8_NUM_U16_DEN => {
let n = source.get_u8();
let d = source.get_u16_le();
(n as u64, d as u64, source)
}
U16_NUM_U16_DEN => {
let n = source.get_u16_le();
let d = source.get_u16_le();
(n as u64, d as u64, source)
}
U32_NUM_U16_DEN => {
let n = source.get_u32_le();
let d = source.get_u16_le();
(n as u64, d as u64, source)
}
U64_NUM_U16_DEN => {
let n = source.get_u64_le();
let d = source.get_u16_le();
(n, d as u64, source)
}
U8_NUM_U32_DEN => {
let n = source.get_u8();
let d = source.get_u32_le();
(n as u64, d as u64, source)
}
U16_NUM_U32_DEN => {
let n = source.get_u16_le();
let d = source.get_u32_le();
(n as u64, d as u64, source)
}
U32_NUM_U32_DEN => {
let n = source.get_u32_le();
let d = source.get_u32_le();
(n as u64, d as u64, source)
}
U64_NUM_U32_DEN => {
let n = source.get_u64_le();
let d = source.get_u32_le();
(n, d as u64, source)
}
U8_NUM_U64_DEN => {
let n = source.get_u8();
let d = source.get_u64_le();
(n as u64, d, source)
}
U16_NUM_U64_DEN => {
let n = source.get_u16_le();
let d = source.get_u64_le();
(n as u64, d, source)
}
U32_NUM_U64_DEN => {
let n = source.get_u32_le();
let d = source.get_u64_le();
(n as u64, d, source)
}
U64_NUM_U64_DEN => {
let n = source.get_u64_le();
let d = source.get_u64_le();
(n, d, source)
}
x => {
unreachable!("Unsupported numerator/denominator type {}", x)
}
}
}
#[inline(always)]
fn get_frac_i64(&self) -> (i64, u64, &[u8]) {
let mut source = self;
let disc = source.get_u8();
let num;
(num, source) = match disc & NUM_MASK {
U8_NUM => {
let v = source.get_u8();
(v as u64, source)
}
U16_NUM => {
let v = source.get_u16_le();
(v as u64, source)
}
U32_NUM => {
let v = source.get_u32_le();
(v as u64, source)
}
U64_NUM => {
let v = source.get_u64_le();
(v, source)
}
x => {
unreachable!("Unsupported numerator type {}", x)
}
};
let den;
(den, source) = match disc & DEN_MASK {
0 => (1u64, source),
U8_DEN => {
let v = source.get_u8();
(v as u64, source)
}
U16_DEN => {
let v = source.get_u16_le();
(v as u64, source)
}
U32_DEN => {
let v = source.get_u32_le();
(v as u64, source)
}
U64_DEN => {
let v = source.get_u64_le();
(v, source)
}
x => {
unreachable!("Unsupported denominator type {}", x)
}
};
let num = if disc & SIGN != 0 {
if num == (1u64 << 63) {
i64::MIN
} else {
-(num as i64)
}
} else {
num as i64
};
(num, den, source)
}
#[inline(always)]
fn skip_rational(&self) -> &[u8] {
let mut dest = self;
let disc = dest.get_u8() & (NUM_MASK | DEN_MASK);
let d = unsafe { *SKIP_TABLE.get_unchecked(disc as usize) };
if d != 0 {
return unsafe { dest.get_unchecked(d as usize..) };
}
let v_num = disc & NUM_MASK;
if v_num == COMPLEX {
dest = dest.skip_rational();
dest = dest.skip_rational();
} else if v_num == ARB_NUM {
let (num_size, den_size);
(num_size, den_size, dest) = dest.get_frac_u64();
let num_size = num_size as usize;
let den_size = den_size as usize;
dest.advance(num_size + den_size);
} else if v_num == RAT_POLY {
let size = dest.get_u32_le() as usize;
dest.advance(size);
} else if v_num == FIN_NUM {
let var_size = dest.get_u8();
let size = get_size_of_natural(var_size & NUM_MASK)
+ get_size_of_natural((var_size & DEN_MASK) >> 4);
dest.advance(size as usize);
} else if v_num == FLOAT {
let size = dest.get_u64_le() as usize;
dest.advance(size);
let size = dest.get_u64_le() as usize;
dest.advance(size);
} else if v_num == INDETERMINATE || v_num == COMPLEX_INFINITY {
} else if v_num == DIRECTED_INFINITY {
dest = dest.skip_rational();
dest = dest.skip_rational();
} else {
unreachable!("Unsupported numerator/denominator type {}", disc)
}
dest
}
#[inline(always)]
fn is_small_int(&self) -> bool {
(self[1] | SIGN) == (U8_NUM | SIGN)
}
#[inline(always)]
fn is_zero_rat(&self) -> bool {
self[1] == U8_NUM && self[2] == 0
}
#[inline(always)]
fn is_one_rat(&self) -> bool {
self[1] == U8_NUM && self[2] == 1
}
}
impl PackedRationalNumberWriter for (i64, u64) {
#[inline(always)]
fn write_packed(&self, dest: &mut Vec<u8>) {
let p = dest.len();
(self.0.unsigned_abs(), self.1).write_packed(dest);
if self.0 < 0 {
dest[p] |= SIGN;
}
}
#[inline(always)]
fn write_packed_fixed(&self, dest: &mut [u8]) {
(self.0.unsigned_abs(), self.1).write_packed_fixed(dest);
if self.0 < 0 {
dest[0] |= SIGN;
}
}
fn get_packed_size(&self) -> u64 {
(self.0.unsigned_abs(), self.1).get_packed_size()
}
}
impl PackedRationalNumberWriter for (u64, u64) {
#[inline(always)]
fn write_packed(&self, dest: &mut Vec<u8>) {
let p = dest.len();
if self.0 <= u8::MAX as u64 {
dest.put_u8(U8_NUM);
dest.put_u8(self.0 as u8);
} else if self.0 <= u16::MAX as u64 {
dest.put_u8(U16_NUM);
dest.put_u16_le(self.0 as u16);
} else if self.0 <= u32::MAX as u64 {
dest.put_u8(U32_NUM);
dest.put_u32_le(self.0 as u32);
} else {
dest.put_u8(U64_NUM);
dest.put_u64_le(self.0);
}
if self.1 == 1 {
} else if self.1 <= u8::MAX as u64 {
dest[p] |= U8_DEN;
dest.put_u8(self.1 as u8);
} else if self.1 <= u16::MAX as u64 {
dest[p] |= U16_DEN;
dest.put_u16_le(self.1 as u16);
} else if self.1 <= u32::MAX as u64 {
dest[p] |= U32_DEN;
dest.put_u32_le(self.1 as u32);
} else {
dest[p] |= U64_DEN;
dest.put_u64_le(self.1);
}
}
#[inline(always)]
fn write_packed_fixed(&self, dest: &mut [u8]) {
let (tag, mut dest) = dest.split_first_mut().unwrap();
if self.0 <= u8::MAX as u64 {
*tag = U8_NUM;
dest.put_u8(self.0 as u8);
} else if self.0 <= u16::MAX as u64 {
*tag = U16_NUM;
dest.put_u16_le(self.0 as u16);
} else if self.0 <= u32::MAX as u64 {
*tag = U32_NUM;
dest.put_u32_le(self.0 as u32);
} else {
*tag = U64_NUM;
dest.put_u64_le(self.0);
}
if self.1 == 1 {
} else if self.1 <= u8::MAX as u64 {
*tag |= U8_DEN;
dest.put_u8(self.1 as u8);
} else if self.1 <= u16::MAX as u64 {
*tag |= U16_DEN;
dest.put_u16_le(self.1 as u16);
} else if self.1 <= u32::MAX as u64 {
*tag |= U32_DEN;
dest.put_u32_le(self.1 as u32);
} else {
*tag |= U64_DEN;
dest.put_u64_le(self.1);
}
}
fn get_packed_size(&self) -> u64 {
let mut size = 1;
size += if self.0 <= u8::MAX as u64 {
get_size_of_natural(U8_NUM)
} else if self.0 <= u16::MAX as u64 {
get_size_of_natural(U16_NUM)
} else if self.0 <= u32::MAX as u64 {
get_size_of_natural(U32_NUM)
} else {
get_size_of_natural(U64_NUM)
};
size += if self.1 == 1 {
0
} else if self.1 <= u8::MAX as u64 {
get_size_of_natural(U8_NUM)
} else if self.1 <= u16::MAX as u64 {
get_size_of_natural(U16_NUM)
} else if self.1 <= u32::MAX as u64 {
get_size_of_natural(U32_NUM)
} else {
get_size_of_natural(U64_NUM)
};
size as u64
}
}