///|
/// A decoded BER length octet(s) (X.690 8.1.3).
pub(all) enum BerLength {
Definite(Int)
Indefinite
} derive(Eq, @debug.Debug)
///|
/// Encode a definite length. Short form is used for `len < 128`, long form
/// otherwise (X.690 8.1.3.4 / 8.1.3.5). Encoding is always definite.
pub fn encode_length(len : Int) -> Bytes {
if len < 128 {
Bytes::from_array([len.to_byte()])
} else {
let acc : Array[Byte] = []
let mut remaining = len
while remaining > 0 {
acc.push((remaining & 0xFF).to_byte())
remaining = remaining >> 8
}
let out = reverse_array(acc)
let head = (out.length() | 0x80).to_byte()
Bytes::from_array([head]) + Bytes::from_array(out)
}
}
///|
/// Encode the identifier octets for a tag, including the long form when the
/// tag number is 31 or greater (X.690 8.1.2.4).
pub fn encode_identifier(tag : BerTag) -> Bytes {
let first = tag.first_octet()
if tag.number < 31 {
Bytes::from_array([first.to_byte()])
} else {
let acc : Array[Byte] = []
let mut remaining = tag.number
while remaining > 0 {
acc.push((remaining & 0x7F).to_byte())
remaining = remaining >> 7
}
let out = reverse_array(acc)
for i in 0..<(out.length() - 1) {
out[i] = (out[i].to_int() | 0x80).to_byte()
}
Bytes::from_array([first.to_byte()]) + Bytes::from_array(out)
}
}
///|
/// Encode a full TLV (tag + length + content).
pub fn encode_tlv(tag : BerTag, content : Bytes) -> Bytes {
encode_identifier(tag) + encode_length(content.length()) + content
}