///|
/// Strict RFC4034 window bitmap. Empty is allowed for NSEC3 empty nonterminals.
pub struct TypeBitmap {
priv types : Array[Int32]
} derive(Eq, Debug)
///|
pub extend TypeBitmap with Eq::{equal, not_equal}
///|
pub extend TypeBitmap with @debug.Debug::{to_repr}
///|
pub fn TypeBitmap::parse(data : Bytes) -> Result[TypeBitmap, DnsError] {
let types : Array[Int32] = []
let mut p = 0
let mut previous = -1
while p < data.length() {
if data.length() - p < 2 {
return Err(Malformed("truncated bitmap header"))
}
let window = data[p].to_int()
let n = data[p + 1].to_int()
p += 2
if window <= previous {
return Err(Malformed("bitmap windows not strictly ordered"))
}
if n < 1 || n > 32 || n > data.length() - p {
return Err(Malformed("bitmap window length"))
}
if data[p + n - 1] == 0 {
return Err(Malformed("non-minimal bitmap window"))
}
for i = 0; i < n; i = i + 1 {
for bit = 0; bit < 8; bit = bit + 1 {
if (data[p + i].to_int() & (128 >> bit)) != 0 {
types.push(window * 256 + i * 8 + bit)
}
}
}
p += n
previous = window
}
Ok({ types, })
}
///|
pub fn TypeBitmap::contains(self : TypeBitmap, rrtype : Int32) -> Bool {
self.types.contains(rrtype)
}
///|
pub fn TypeBitmap::types(self : TypeBitmap) -> Array[Int32] {
self.types.copy()
}
///|
pub fn TypeBitmap::encode(self : TypeBitmap) -> Bytes {
let out : Array[Byte] = []
let mut p = 0
while p < self.types.length() {
let window = self.types[p] / 256
let bits : Array[Byte] = Array::make(32, 0)
let mut length = 0
while p < self.types.length() && self.types[p] / 256 == window {
let t = self.types[p] % 256
let i = t / 8
bits[i] = (bits[i].to_int() | (128 >> (t % 8))).to_byte()
if i + 1 > length {
length = i + 1
}
p += 1
}
out.push(window.to_byte())
out.push(length.to_byte())
for i = 0; i < length; i = i + 1 {
out.push(bits[i])
}
}
Bytes::from_array(out)
}