///|
/// Parse the content octets of an INTEGER value into a signed `Int`, rejecting
/// integers wider than `max_bytes`.
pub fn parse_integer(content : Bytes, max_bytes : Int) -> Result[Int, BerError] {
result_of_ber(fn() raise BerError {
let n = content.length()
if n == 0 {
raise Truncated
}
if n > max_bytes || n * 8 >= 64 {
raise IntegerTooLarge
}
let mut value = 0
for i in 0.. Result[Bool, BerError] {
result_of_ber(fn() raise BerError {
if content.length() == 0 {
raise Truncated
}
let mut any = false
for b in content {
if b != 0 {
any = true
}
}
any
})
}
///|
/// Decode a BER INTEGER value, checking the tag is INTEGER and the width
/// respects `limits`.
pub fn decode_integer(
value : BerValue,
limits : BerLimits,
) -> Result[Int, BerError] {
if value.tag.class != Universal || value.tag.number != tag_integer {
return Err(InvalidTag)
}
parse_integer(value.content, limits.max_integer_bytes)
}
///|
/// Decode a BER BOOLEAN value.
pub fn decode_boolean(value : BerValue) -> Result[Bool, BerError] {
if value.tag.class != Universal || value.tag.number != tag_boolean {
return Err(InvalidTag)
}
parse_boolean(value.content)
}
///|
/// Parse the content octets of an OID into its dotted-decimal form (X.690 8.19).
pub fn parse_oid(content : Bytes) -> Result[String, BerError] {
result_of_ber(fn() raise BerError {
let n = content.length()
if n == 0 {
raise InvalidOid
}
let arcs : Array[Int] = []
let mut current = 0
let mut complete = true
for b in content {
let v = b.to_int()
current = current * 128 + (v & 0x7F)
if (v & 0x80) == 0 {
arcs.push(current)
current = 0
complete = true
} else {
complete = false
}
}
if !complete {
raise InvalidOid
}
if arcs.is_empty() {
raise InvalidOid
}
let first_combined = arcs[0]
let first = if first_combined < 40 {
0
} else if first_combined < 80 {
1
} else {
2
}
let second = first_combined - first * 40
let sb = StringBuilder()
sb.write_string("\{first}.\{second}")
for i in 1.. Result[String, BerError] {
if value.tag.class != Universal || value.tag.number != tag_oid {
return Err(InvalidTag)
}
parse_oid(value.content)
}