| Crates.io | asn1_len |
| lib.rs | asn1_len |
| version | 2.0.0 |
| created_at | 2025-08-17 11:36:48.515808+00 |
| updated_at | 2025-09-08 08:12:22.127264+00 |
| description | A utilities to convert back and forth between unsigned int and ASN.1 Length. |
| homepage | |
| repository | https://github.com/NattapongSiri/asn1_len_rs |
| max_upload_size | |
| id | 1799345 |
| size | 50,242 |
A crate that allow transformation between ASN.1 Length object and various unsigned int types.
This crate provides following feature gates:
primitive - Provides Asn1Len struct and the way to convert back and forth with primitive type.bigint - Similar to primitve with additional support for convert back and forth with crypto_bigint::Uint and crypto_bigint::BoxedUint.macro - Provides a utility function value_def which is a helper function to encode ASN.1 Length value from LitInt.full - All above features are enabled.The default feature is primitive.
To use with standard Rust unsigned integer type:
cargo add asn1_len
To use with big unsigned integer:
cargo add asn1_len --features bigint
To use macro helper function:
cargo add asn1_len --features macro
To enable all features:
cargo add asn1_len --features full
macro feature - Compile time ASN.1 Length declarationWith feature gate macro,
This crate provides value_def helper function to parse/tranform LitInt when dealing with procedural macro. The function return tuple of (TokenStream, usize).
The TokenStream contains a comma separated value of LitInt which conform to ASN.1 format. Each LitInt is a byte. If there're more than one byte, the first byte is encoded length of the length itself. See this wiki for how it encode the length.
The usize contains a number of LitInt inside the TokenStream including the encoded length byte.
It is mandatory that the procedural macro that make use of this function must produce a complete valid syntax of Rust.
Build fixed size array of ASN.1 Length
let (token, size) = asn1_len::value_def!(128);
quote! { [#token; #size] } // Build a fixed size array of ASN.1 Length
With feature gate primitive,
This crate provides struct Asn1Len. The struct provides method with_header and without_header. with_header returns a slice contains a complete byte sequence including an encoded length of the length itself. See this wiki for how it encode the length. . without_header simply return length value encoded as big-endian byte sequence. The only different between the two is the first byte. without_header excludes the first byte of with_header method.
To construct Asn1Len, there are 3 methods.
With feature gate primitive, or bigint:
Asn1Len::from_primitive or Asn1Len::from using std::convert::From trait. It allow any of Rust unsigned integer primitive to be convert into Asn1Len.Only with feature gate bigint:
Asn1Len::from_big_uint method to create an encoded ASN.1 Length out of given Uint object.Asn1Len::from_boxed_big_uint method to create an encoded ASN.1 Length out of given BoxedUint object.Only Asn1Len::from_primitive guarantee to return Asn1Len. The others return Result which if value is too big to be encoded into ASN.1 Length, it return OverflowError.
To work with Asn1Len, this required a convert back from Asn1Len object into some kind of workable type such as Rust primitive data type or those of Uint variants.
This crate provide 3 methods.
This method available on both feature bigint and primitive:
Asn1Len::to_primitive. It allow a conversion to one of unsigned integer type of Rust. If value cannot be fit into such type, it return OverflowError.These methods available onfeature bigint only:
Asn1Len::to_big_uint. It allow a conversion to crypto_bigint::Uint type. If the LIMB specified is not large enough to accommodate current ASN.1 Length, it return OverflowError.Asn1Len::to_boxed_big_uint. It allow a conversion to crypto_bigint::BoxedUint type.Only Asn1Len::to_boxed_big_uint guarantee to return BoxedUint. The others return Result which if value is too big to be accommodate to target type, it return OverflowError.
use asn1_len::Asn1Len;
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(); // Value too large to fit into u8
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(); // Value too large to fit into this Uint with 1 limb
let variable_len = big_len.to_boxed_big_uint().widen(4096); // Make 4096 bits with value from previous big_len
variable_len.checked_add(&Uint::<32>::MAX.into()).unwrap();
// Make largest possible length in ASN.1 Length specification
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(); // it should succeed.
let overflow_val = max_val.checked_add(&Uint::ONE).unwrap(); // Add 1 to max_len
Asn1Len::from_big_uint(&overflow_val).unwrap_err(); // It should overflow when turn it into ASN.1 Length
Split library into 3 main features. The default features is primitive. The equivalence to version 1.x.x is full.
cargo add asn1_len --features full
Asn1Len now implements PartialEq, Eq, PartialOrd, and Ord