use std::fmt::{Debug, Display};
use num_traits::{NumCast, ToBytes, ToPrimitive, Unsigned};
use proc_macro2::TokenStream;
use quote::quote;
use syn::LitInt;
use crypto_bigint::{BoxedUint, Encoding, Limb, Uint};
pub struct OverflowError {}
impl Display for OverflowError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Size is too large to fit into target data type.")
}
}
impl Debug for OverflowError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
<Self as Display>::fmt(&self, f)
}
}
impl std::error::Error for OverflowError {}
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord)]
pub struct Asn1Len(Vec<u8>);
impl Asn1Len {
pub fn with_header(&self) -> &[u8] {
&self.0
}
pub fn without_header(&self) -> &[u8] {
if self.0.len() > 1 {
&self.0[1..]
} else {
&self.0[0..1]
}
}
pub fn from_primitive<T>(value: T) -> Self where T: From<u8> + ToBytes + PartialOrd + Unsigned {
Self::from(value)
}
pub fn to_primitive<T>(&self) -> Result<T, OverflowError> where T: Unsigned + NumCast {
NumCast::from(self).ok_or(OverflowError { })
}
pub fn from_big_uint<const N: usize>(value: &Uint<N>) -> Result<Self, OverflowError> {
let size = value.bits().div_ceil(8) as usize;
if size == 0 {
return Ok(Asn1Len(vec![0]))
}
if size >= 0x7F {
return Err(OverflowError { })
}
let mut vec = Vec::with_capacity(size + 1);
if value.bits() > 7 {
vec.push(size as u8 | 0x80);
}
let limbs = &value.as_limbs()[0..(size.div_ceil(Limb::BYTES))];
vec.extend_from_slice(&limbs[limbs.len() - 1].to_be_bytes().as_slice()[((Limb::BYTES - 1 - ((value.bits() - 1) % Limb::BITS) as usize / 8))..]);
limbs[..(limbs.len() - 1)].iter().rev().for_each(|limb| {
vec.extend_from_slice(&limb.to_be_bytes());
});
Ok(Self(vec))
}
pub fn to_big_uint<const LIMB: usize>(&self) -> Result<Uint<LIMB>, OverflowError> {
if self.0.len() == 1 {
Ok(Uint::<LIMB>::from_u8(self.0[0]))
} else {
let min_size: usize = self.0.len() - 1;
if min_size > LIMB * Limb::BYTES {
return Err(OverflowError { })
}
let mut temp: Vec<u8> = vec![0; LIMB * Limb::BYTES - min_size];
temp.extend_from_slice(&self.0[1..]);
Ok(Uint::<LIMB>::from_be_slice(temp.as_slice()))
}
}
pub fn from_boxed_big_uint(value: &BoxedUint) -> Result<Self, OverflowError> {
let size = value.bits().div_ceil(8) as usize;
if size == 0 {
return Ok(Asn1Len(vec![0]))
}
if size >= 0x7F {
return Err(OverflowError { })
}
let mut vec = Vec::with_capacity(size + 1);
if value.bits() > 7 {
vec.push(size as u8 | 0x80);
}
let bytes = value.to_be_bytes();
vec.extend_from_slice(&bytes[(bytes.len() - ((value.bits() as usize - 1) / 8) - 1)..]);
Ok(Self(vec))
}
pub fn to_boxed_big_uint(&self) -> BoxedUint {
let precision = self.0.len() * 8;
if self.0.len() > 1 {
BoxedUint::from_be_slice(&self.0[1..], precision as u32 - 8).unwrap()
} else {
BoxedUint::from(self.0[0])
}
}
}
impl<T> From<T> for Asn1Len where T: From<u8> + ToBytes + PartialOrd + Unsigned {
fn from(value: T) -> Self {
if value < T::from(127u8) {
Asn1Len(vec![value.to_le_bytes().as_ref()[0]])
} else {
let raw_bytes = value.to_be_bytes();
let bytes = raw_bytes.as_ref();
let n = bytes.len();
if n < 0x7F {
let mut vec = Vec::<u8>::with_capacity(n + 1);
let first_index = bytes.iter().position(|b| *b != 0).unwrap_or(bytes.len() - 1);
vec.push((bytes.len() - first_index) as u8 | 0x80);
vec.extend_from_slice(&bytes[first_index..]);
Asn1Len(vec)
} else {
panic!("Value is too big to fit into ASN.1 Integer.")
}
}
}
}
impl Into<u8> for Asn1Len {
fn into(self) -> u8 {
self.0[self.0.len() - 1]
}
}
impl ToPrimitive for Asn1Len {
fn to_f32(&self) -> Option<f32> {
None
}
fn to_f64(&self) -> Option<f64> {
None
}
fn to_i128(&self) -> Option<i128> {
None
}
fn to_i16(&self) -> Option<i16> {
None
}
fn to_i32(&self) -> Option<i32> {
None
}
fn to_i64(&self) -> Option<i64> {
None
}
fn to_i8(&self) -> Option<i8> {
None
}
fn to_isize(&self) -> Option<isize> {
None
}
fn to_u128(&self) -> Option<u128> {
if self.0.len() == 1 {
Some(self.0[0] as u128)
} else if self.0.len() - 1 > 16 {
None
} else if self.0[0] < 127 {
Some(self.0[0] as u128)
} else {
Some(
self.0[1..].iter().fold(0u128, |acc, b| {
(acc << 8) | *b as u128
})
)
}
}
fn to_u16(&self) -> Option<u16> {
if self.0.len() - 1 > 2 {
None
} else if self.0[0] < 127 {
Some(self.0[0] as u16)
} else {
Some(
self.0[1..].iter().fold(0u16, |acc, b| {
(acc << 8) | *b as u16
})
)
}
}
fn to_u32(&self) -> Option<u32> {
if self.0.len() - 1 > 4 {
None
} else if self.0[0] < 127 {
Some(self.0[0] as u32)
} else {
Some(
self.0[1..].iter().fold(0u32, |acc, b| {
(acc << 8) | *b as u32
})
)
}
}
fn to_u64(&self) -> Option<u64> {
if self.0.len() - 1 > 8 {
None
} else if self.0[0] < 127 {
Some(self.0[0] as u64)
} else {
Some(
self.0[1..].iter().fold(064, |acc, b| {
(acc << 8) | *b as u64
})
)
}
}
fn to_u8(&self) -> Option<u8> {
if self.0.len() - 1 > 1 {
None
} else if self.0.len() == 1 {
Some(self.0[0])
} else {
Some(self.0[1])
}
}
fn to_usize(&self) -> Option<usize> {
if self.0.len() - 1 > usize::BITS as usize / 8 {
None
} else if self.0[0] < 127 {
Some(self.0[0] as usize)
} else {
Some(
self.0[1..].iter().fold(0usize, |acc, b| {
(acc << 8) | *b as usize
})
)
}
}
}
impl ToPrimitive for &'_ Asn1Len {
fn to_f32(&self) -> Option<f32> {
None
}
fn to_f64(&self) -> Option<f64> {
None
}
fn to_i128(&self) -> Option<i128> {
None
}
fn to_i16(&self) -> Option<i16> {
None
}
fn to_i32(&self) -> Option<i32> {
None
}
fn to_i64(&self) -> Option<i64> {
None
}
fn to_i8(&self) -> Option<i8> {
None
}
fn to_isize(&self) -> Option<isize> {
None
}
fn to_u128(&self) -> Option<u128> {
if self.0.len() == 1 {
Some(self.0[0] as u128)
} else if self.0.len() - 1 > 16 {
None
} else if self.0[0] < 127 {
Some(self.0[0] as u128)
} else {
Some(
self.0[1..].iter().fold(0u128, |acc, b| {
(acc << 8) | *b as u128
})
)
}
}
fn to_u16(&self) -> Option<u16> {
if self.0.len() - 1 > 2 {
None
} else if self.0[0] < 127 {
Some(self.0[0] as u16)
} else {
Some(
self.0[1..].iter().fold(0u16, |acc, b| {
(acc << 8) | *b as u16
})
)
}
}
fn to_u32(&self) -> Option<u32> {
if self.0.len() - 1 > 4 {
None
} else if self.0[0] < 127 {
Some(self.0[0] as u32)
} else {
Some(
self.0[1..].iter().fold(0u32, |acc, b| {
(acc << 8) | *b as u32
})
)
}
}
fn to_u64(&self) -> Option<u64> {
if self.0.len() - 1 > 8 {
None
} else if self.0[0] < 127 {
Some(self.0[0] as u64)
} else {
Some(
self.0[1..].iter().fold(064, |acc, b| {
(acc << 8) | *b as u64
})
)
}
}
fn to_u8(&self) -> Option<u8> {
if self.0.len() - 1 > 1 {
None
} else if self.0.len() == 1 {
Some(self.0[0])
} else {
Some(self.0[1])
}
}
fn to_usize(&self) -> Option<usize> {
if self.0.len() - 1 > usize::BITS as usize / 8 {
None
} else if self.0[0] < 127 {
Some(self.0[0] as usize)
} else {
Some(
self.0[1..].iter().fold(0usize, |acc, b| {
(acc << 8) | *b as usize
})
)
}
}
}
pub fn value_def(int: LitInt) -> (TokenStream, usize) {
let val_str = int.base10_digits();
if val_str == "0" {
return (quote! { 0 }, 1)
}
let parsed = BoxedUint::from_str_radix_vartime(val_str, 10).unwrap();
if parsed.bits() > 127 * 8 {
panic!("Value is too big to be put in ASN.1 Length type.");
}
let bytes = parsed.to_be_bytes();
let compacted = bytes.split_at(bytes.len() - ((parsed.bits() as usize - 1) / 8) - 1).1;
let (size, final_size) = if compacted.len() > 1 || compacted[0] > 127 {
let l = compacted.len() as u8 | 0x80;
(quote! { #l, }, compacted.len() + 1)
} else {
(quote! {}, compacted.len())
};
(quote! { #size #(#compacted,)* }.into(), final_size)
}
#[cfg(test)]
mod tests {
use std::usize;
use crate::Asn1Len;
use super::value_def;
use crypto_bigint::{BoxedUint, CheckedAdd, Encoding, Limb, Uint};
use syn::{parse::Parse, parse2, punctuated::Punctuated, LitInt, Token};
use quote::quote;
#[allow(unused)]
struct Csv {
values: Punctuated<LitInt, Token![,]>
}
impl PartialEq<[u8]> for Csv {
fn eq(&self, other: &'_ [u8]) -> bool {
self.values.iter().zip(other.iter()).all(|(lhs, rhs)| {
lhs.base10_parse::<u8>().unwrap() == *rhs
})
}
}
impl Parse for Csv {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
Ok(Csv {
values: Punctuated::parse_terminated(input)?
})
}
}
#[test]
fn short_val_0() {
let input = quote! { 0 };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 1);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0]));
}
#[test]
fn short_val_1() {
let input = quote! { 1 };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 1);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[1]));
}
#[test]
fn short_val_127() {
let input = quote! { 127 };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 1);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[127]));
}
#[test]
fn long_val_128() {
let input = quote! { 128 };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 2);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x81, 128]));
}
#[test]
fn long_val_0xff() {
let input = quote! { 0xFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 2);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x81, 0xFF]));
}
#[test]
fn long_val_0x00ff() {
let input = quote! { 0x00FF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 2);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x81, 0xFF]));
}
#[test]
fn long_val_0x01ff() {
let input = quote! { 0x01FF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 3);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x82, 0x01, 0xFF]));
}
#[test]
fn long_val_0x80ff() {
let input = quote! { 0x80FF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 3);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x82, 0x80, 0xFF]));
}
#[test]
fn long_val_0xffff() {
let input = quote! { 0xFFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 3);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x82, 0xFF, 0xFF]));
}
#[test]
fn long_val_0x01ffff() {
let input = quote! { 0x01FFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 4);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x83, 0x01, 0xFF, 0xFF]));
}
#[test]
fn long_val_0x80ffff() {
let input = quote! { 0x80FFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 4);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x83, 0x80, 0xFF, 0xFF]));
}
#[test]
fn long_val_0xffffff() {
let input = quote! { 0xFFFFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 4);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x83, 0xFF, 0xFF, 0xFF]));
}
#[test]
fn long_val_0x01ffffff() {
let input = quote! { 0x01FFFFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 5);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x84, 0x01, 0xFF, 0xFF, 0xFF]));
}
#[test]
fn long_val_0x80ffffff() {
let input = quote! { 0x80FFFFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 5);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x84, 0x80, 0xFF, 0xFF, 0xFF]));
}
#[test]
fn long_val_0xffffffff() {
let input = quote! { 0xFFFFFFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 5);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x84, 0xFF, 0xFF, 0xFF, 0xFF]));
}
#[test]
fn long_val_0x80ffffffff() {
let input = quote! { 0x80FFFFFFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 6);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x85, 0x80, 0xFF, 0xFF, 0xFF, 0xFF]));
}
#[test]
fn long_val_0xffffffffff() {
let input = quote! { 0xFFFFFFFFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 6);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x85, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]));
}
#[test]
fn long_val_0xffffffffffff() {
let input = quote! { 0xFFFFFFFFFFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 7);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x86, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]));
}
#[test]
fn long_val_0xffffffffffffff() {
let input = quote! { 0xFFFFFFFFFFFFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 8);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]));
}
#[test]
fn long_val_0x01ffffffffffffff() {
let input = quote! { 0x01FFFFFFFFFFFFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 9);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x88, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]));
}
#[test]
fn long_val_0x80ffffffffffffff() {
let input = quote! { 0x80FFFFFFFFFFFFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 9);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x88, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]));
}
#[test]
fn long_val_0xffffffffffffffff() {
let input = quote! { 0xFFFFFFFFFFFFFFFF };
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 9);
let values: Csv = parse2(tokens).unwrap();
assert!(values.eq(&[0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]));
}
#[test]
fn def_one_of_max() {
let input = quote! {
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
};
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 128);
let mut values: Csv = parse2(tokens).unwrap();
assert_eq!(values.values.len(), 128);
assert_eq!(values.values.pop().unwrap().into_value().base10_digits(), "254");
assert!(values.values.iter().map(|lit| lit.base10_digits()).all(|p| p.eq("255")));
}
#[test]
fn def_max() {
let input = quote! {
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
};
let int: LitInt = parse2(input).unwrap();
let (tokens, size) = value_def(int);
assert_eq!(size, 128);
let values: Csv = parse2(tokens).unwrap();
assert_eq!(values.values.len(), 128);
assert!(values.values.iter().map(|lit| lit.base10_digits()).all(|p| p.eq("255")));
}
#[test]
#[should_panic]
fn def_overflow() {
let input = quote! {
0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
};
let int: LitInt = parse2(input).unwrap();
value_def(int);
}
#[test]
fn from_big_uint() {
let val = Asn1Len::from_big_uint(&Uint::<2>::from_u8(0)).unwrap();
assert_eq!(val.with_header(), &[0]);
assert_eq!(val.without_header(), &[0]);
let val = Asn1Len::from_big_uint(&Uint::<2>::from_u8(1)).unwrap();
assert_eq!(val.with_header(), &[1]);
assert_eq!(val.without_header(), &[1]);
let val = Asn1Len::from_big_uint(&Uint::<2>::from_u8(0xFF)).unwrap();
assert_eq!(val.with_header(), &[0x81, 0xFF]);
assert_eq!(val.without_header(), &[0xFF]);
let val = Asn1Len::from_big_uint(&Uint::<2>::from_u16(0)).unwrap();
assert_eq!(val.with_header(), &[0]);
assert_eq!(val.without_header(), &[0]);
let val = Asn1Len::from_big_uint(&Uint::<2>::from_u16(1)).unwrap();
assert_eq!(val.with_header(), &[1]);
assert_eq!(val.without_header(), &[1]);
let val = Asn1Len::from_big_uint(&Uint::<2>::from_u16(0xFF)).unwrap();
assert_eq!(val.with_header(), &[0x81, 0xFF]);
assert_eq!(val.without_header(), &[0xFF]);
let val = Asn1Len::from_big_uint(&Uint::<2>::from_u16(0xFFFF)).unwrap();
assert_eq!(val.with_header(), &[0x82, 0xFF, 0xFF]);
assert_eq!(val.without_header(), &[0xFF, 0xFF]);
let val = Asn1Len::from_big_uint(&Uint::<2>::from_u16(0xF000)).unwrap();
assert_eq!(val.with_header(), &[0x82, 0xF0, 0x00]);
assert_eq!(val.without_header(), &[0xF0, 0x00]);
let val = Asn1Len::from_big_uint(&Uint::<2>::from_u32(0xF123F000)).unwrap();
assert_eq!(val.with_header(), &[0x84, 0xF1, 0x23, 0xF0, 0x00]);
assert_eq!(val.without_header(), &[0xF1, 0x23, 0xF0, 0x00]);
let val = Asn1Len::from_big_uint(&Uint::<2>::from_u64(0x81238000F123F000)).unwrap();
assert_eq!(val.with_header(), &[0x88, 0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00]);
assert_eq!(val.without_header(), &[0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00]);
let val = Asn1Len::from_big_uint(&Uint::<2>::from_u128(0x0181238000F123F000)).unwrap();
assert_eq!(val.with_header(), &[0x89, 0x01, 0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00]);
assert_eq!(val.without_header(), &[0x01, 0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00]);
let val = Asn1Len::from_big_uint(&Uint::<2>::from_u128(0x81238000F123F00081238000F123F000)).unwrap();
assert_eq!(val.with_header(), &[0x90, 0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00, 0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00]);
assert_eq!(val.without_header(), &[0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00, 0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00]);
}
#[test]
fn to_big_uint_failed() {
Asn1Len::from_big_uint(&Uint::<2>::MAX).unwrap().to_big_uint::<1>().unwrap_err();
}
#[test]
fn from_boxed_big_uint() {
let val = Asn1Len::from_boxed_big_uint(&Uint::<2>::from_u8(0).into()).unwrap();
assert_eq!(val.with_header(), &[0]);
assert_eq!(val.without_header(), &[0]);
let val = Asn1Len::from_boxed_big_uint(&Uint::<2>::from_u8(1).into()).unwrap();
assert_eq!(val.with_header(), &[1]);
assert_eq!(val.without_header(), &[1]);
let val = Asn1Len::from_boxed_big_uint(&Uint::<2>::from_u8(0xFF).into()).unwrap();
assert_eq!(val.with_header(), &[0x81, 0xFF]);
assert_eq!(val.without_header(), &[0xFF]);
let val = Asn1Len::from_boxed_big_uint(&Uint::<2>::from_u16(0).into()).unwrap();
assert_eq!(val.with_header(), &[0]);
assert_eq!(val.without_header(), &[0]);
let val = Asn1Len::from_boxed_big_uint(&Uint::<2>::from_u16(1).into()).unwrap();
assert_eq!(val.with_header(), &[1]);
assert_eq!(val.without_header(), &[1]);
let val = Asn1Len::from_boxed_big_uint(&Uint::<2>::from_u16(0xFF).into()).unwrap();
assert_eq!(val.with_header(), &[0x81, 0xFF]);
assert_eq!(val.without_header(), &[0xFF]);
let val = Asn1Len::from_boxed_big_uint(&Uint::<2>::from_u16(0xFFFF).into()).unwrap();
assert_eq!(val.with_header(), &[0x82, 0xFF, 0xFF]);
assert_eq!(val.without_header(), &[0xFF, 0xFF]);
let val = Asn1Len::from_boxed_big_uint(&Uint::<2>::from_u16(0xF000).into()).unwrap();
assert_eq!(val.with_header(), &[0x82, 0xF0, 0x00]);
assert_eq!(val.without_header(), &[0xF0, 0x00]);
let val = Asn1Len::from_boxed_big_uint(&Uint::<2>::from_u32(0xF123F000).into()).unwrap();
assert_eq!(val.with_header(), &[0x84, 0xF1, 0x23, 0xF0, 0x00]);
assert_eq!(val.without_header(), &[0xF1, 0x23, 0xF0, 0x00]);
let val = Asn1Len::from_boxed_big_uint(&Uint::<2>::from_u64(0x81238000F123F000).into()).unwrap();
assert_eq!(val.with_header(), &[0x88, 0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00]);
assert_eq!(val.without_header(), &[0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00]);
let val = Asn1Len::from_boxed_big_uint(&Uint::<2>::from_u128(0x0181238000F123F000).into()).unwrap();
assert_eq!(val.with_header(), &[0x89, 0x01, 0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00]);
assert_eq!(val.without_header(), &[0x01, 0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00]);
let val = Asn1Len::from_boxed_big_uint(&Uint::<2>::from_u128(0x81238000F123F00081238000F123F000).into()).unwrap();
assert_eq!(val.with_header(), &[0x90, 0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00, 0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00]);
assert_eq!(val.without_header(), &[0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00, 0x81, 0x23, 0x80, 0x00, 0xF1, 0x23, 0xF0, 0x00]);
}
#[test]
fn overflow() {
Asn1Len::from_big_uint(&Uint::<128>::from_u8(0).not()).unwrap_err();
}
#[test]
fn to_primitive() {
let value: u8 = Asn1Len::from(0u8).to_primitive().unwrap();
assert_eq!(value, 0);
let value: u8 = Asn1Len::from(1u8).to_primitive().unwrap();
assert_eq!(value, 1);
let value: u8 = Asn1Len::from(u8::MAX).to_primitive().unwrap();
assert_eq!(value, u8::MAX);
let value: u8 = Asn1Len::from(1u16).to_primitive().unwrap();
assert_eq!(value, 1);
let value: u16 = Asn1Len::from(0u8).to_primitive().unwrap();
assert_eq!(value, 0u16);
let value: u16 = Asn1Len::from(1u8).to_primitive().unwrap();
assert_eq!(value, 1u16);
let value: u16 = Asn1Len::from(u16::MAX).to_primitive().unwrap();
assert_eq!(value, u16::MAX);
let value: u32 = Asn1Len::from(0u32).to_primitive().unwrap();
assert_eq!(value, 0u32);
let value: u32 = Asn1Len::from(1u32).to_primitive().unwrap();
assert_eq!(value, 1u32);
let value: u32 = Asn1Len::from(u32::MAX).to_primitive().unwrap();
assert_eq!(value, u32::MAX);
let value: u64 = Asn1Len::from(0u64).to_primitive().unwrap();
assert_eq!(value, 0u64);
let value: u64 = Asn1Len::from(1u64).to_primitive().unwrap();
assert_eq!(value, 1u64);
let value: u64 = Asn1Len::from(u64::MAX).to_primitive().unwrap();
assert_eq!(value, u64::MAX);
let value: u128 = Asn1Len::from(0u128).to_primitive().unwrap();
assert_eq!(value, 0u128);
let value: u128 = Asn1Len::from(1u128).to_primitive().unwrap();
assert_eq!(value, 1u128);
let value: u128 = Asn1Len::from(u128::MAX).to_primitive().unwrap();
assert_eq!(value, u128::MAX);
assert!(Asn1Len::from(0x01FFu16).to_primitive::<u8>().is_err());
let value: usize = Asn1Len::from(0u8).to_primitive().unwrap();
assert_eq!(value, 0);
let value: usize = Asn1Len::from(usize::MAX).to_primitive().unwrap();
assert_eq!(value, usize::MAX);
}
#[test]
fn to_big_uint() {
let value = Asn1Len::from_primitive(0u8).to_big_uint::<1>().unwrap();
assert_eq!(value, Uint::ZERO);
let value = Asn1Len::from_primitive(1u8).to_big_uint::<1>().unwrap();
assert_eq!(value, Uint::ONE);
let value = Asn1Len::from_primitive(0x7Fu8).to_big_uint::<1>().unwrap();
assert_eq!(value, Uint::from_u8(0x7Fu8));
let value = Asn1Len::from_primitive(0x80u8).to_big_uint::<1>().unwrap();
assert_eq!(value, Uint::from_u8(0x80u8));
let value = Asn1Len::from_primitive(0xFFu8).to_big_uint::<1>().unwrap();
assert_eq!(value, Uint::from_u8(0xFFu8));
let value = Asn1Len::from_primitive(0u128).to_big_uint::<1>().unwrap();
assert_eq!(value, Uint::ZERO);
let value = Asn1Len::from_primitive(0xFFu128).to_big_uint::<1>().unwrap();
assert_eq!(value, Uint::from_u8(0xFFu8));
let value = Asn1Len::from_primitive(u128::MAX).to_big_uint::<2>().unwrap();
assert_eq!(value, Uint::from_u128(u128::MAX));
let value = Asn1Len::from_big_uint(&Uint::<2>::MAX).unwrap().to_big_uint::<2>().unwrap();
assert!(value.checked_add(&Uint::ONE).into_option().is_none());
}
#[test]
fn to_boxed_big_uint() {
let value = Asn1Len::from_primitive(0u8).to_boxed_big_uint();
assert_eq!(value, BoxedUint::zero());
let value = Asn1Len::from_primitive(1u8).to_boxed_big_uint();
assert_eq!(value, BoxedUint::one());
let value = Asn1Len::from_primitive(0x7Fu8).to_boxed_big_uint();
assert_eq!(value, BoxedUint::from_be_slice(&[0x7Fu8], 8).unwrap());
let value = Asn1Len::from_primitive(0x80u8).to_boxed_big_uint();
assert_eq!(value, BoxedUint::from_be_slice(&[0x80u8], 8).unwrap());
let value = Asn1Len::from_primitive(0xFFu8).to_boxed_big_uint();
assert_eq!(value, BoxedUint::from_be_slice(&[0xFFu8], 8).unwrap());
let value = Asn1Len::from_primitive(0u128).to_boxed_big_uint();
assert_eq!(value, BoxedUint::zero());
let value = Asn1Len::from_primitive(0xFFu128).to_boxed_big_uint();
assert_eq!(value, BoxedUint::from_be_slice(&[0xFFu8], 8).unwrap());
let value = Asn1Len::from_primitive(u128::MAX).to_boxed_big_uint();
assert_eq!(value, BoxedUint::from_be_slice(&u128::MAX.to_be_bytes(), 128).unwrap());
let value = Asn1Len::from_big_uint(&Uint::<2>::MAX).unwrap().to_boxed_big_uint();
assert!(value.checked_add(&BoxedUint::one()).into_option().is_none());
let value = value.widen(value.bits_precision() + 1);
value.checked_add(&BoxedUint::one()).unwrap();
}
#[test]
fn test() {
let len = Asn1Len::from_primitive(1u8);
assert_eq!(len.with_header(), &[1u8]);
let new_len = Asn1Len::from_primitive(len.to_primitive::<u16>().unwrap() + 255);
assert_eq!(new_len.with_header(), &[0x82u8, 0x01, 0x00]);
new_len.to_primitive::<u8>().unwrap_err(); let big_len = Asn1Len::from_big_uint(&crypto_bigint::Uint::<{127 / crypto_bigint::Limb::BYTES as usize}>::MAX).unwrap();
big_len.to_big_uint::<1>().unwrap_err(); let variable_len = big_len.to_boxed_big_uint().widen(4096); variable_len.checked_add(&Uint::<32>::MAX.into()).unwrap();
let mut max_len: [u8; 128] = [0xFF; 128];
max_len[0] = 0;
max_len[1] = 0;
let max_val = crypto_bigint::Uint::<{128 / Limb::BYTES as usize}>::from_be_bytes(max_len);
Asn1Len::from_big_uint(&max_val).unwrap();
let overflow_val = max_val.checked_add(&Uint::ONE).unwrap();
Asn1Len::from_big_uint(&overflow_val).unwrap_err();
}
#[test]
fn inequality_than() {
let lesser = Asn1Len::from_primitive(0u8);
let bigger = Asn1Len::from_primitive(u16::MAX);
assert!(lesser < bigger);
assert!(bigger > lesser);
assert!(lesser <= bigger);
assert!(bigger >= lesser);
assert!(bigger != lesser);
assert!(lesser != bigger);
let lesser = Asn1Len::from_primitive(0u8);
let bigger = Asn1Len::from_primitive(1u8);
assert!(lesser < bigger);
assert!(bigger > lesser);
assert!(lesser <= bigger);
assert!(bigger >= lesser);
assert!(bigger != lesser);
assert!(lesser != bigger);
let lesser = Asn1Len::from_primitive(1u8);
let bigger = Asn1Len::from_primitive(u64::MAX - 1);
assert!(lesser < bigger);
assert!(bigger > lesser);
assert!(lesser <= bigger);
assert!(bigger >= lesser);
assert!(bigger != lesser);
assert!(lesser != bigger);
let lesser = Asn1Len::from_primitive(u8::MAX);
let bigger = Asn1Len::from_primitive(u16::MAX);
assert!(lesser < bigger);
assert!(bigger > lesser);
assert!(lesser <= bigger);
assert!(bigger >= lesser);
assert!(bigger != lesser);
assert!(lesser != bigger);
}
#[test]
fn equals_test() {
let lhs = Asn1Len::from_primitive(0u8);
let rhs = Asn1Len::from_primitive(0u8);
assert_eq!(lhs, rhs);
let lhs = Asn1Len::from_primitive(1u8);
let rhs = Asn1Len::from_primitive(1u16);
assert_eq!(lhs, rhs);
let lhs = Asn1Len::from_primitive(u16::MAX);
let rhs = Asn1Len::from_primitive(65535u16);
assert_eq!(lhs, rhs);
let lhs = Asn1Len::from_primitive(usize::MAX);
let rhs = Asn1Len::from_big_uint(&Uint::<1>::MAX).unwrap();
assert_eq!(lhs, rhs);
}
#[test]
fn sort_test() {
let mut test = vec![Asn1Len::from_primitive(1u8), Asn1Len::from_primitive(256u16), Asn1Len::from_primitive(0u8), Asn1Len::from_primitive(255u8), Asn1Len::from_primitive(127u8)];
test.sort();
test.windows(2).for_each(|pair| {
assert!(pair[0] < pair[1]);
});
}
}