///|
priv struct Reader {
data : Bytes
mut pos : Int32
}
///|
fn Reader::new(data : Bytes, limits : Limits) -> Reader raise BacnetError {
limits.validate()
if data.length() > limits.max_bytes {
raise Limit("input bytes")
}
{ data, pos: 0, }
}
///|
fn Reader::remaining(self : Reader) -> Int32 {
self.data.length() - self.pos
}
///|
fn Reader::u8(self : Reader) -> Int32 raise BacnetError {
if self.remaining() == 0 {
raise Invalid("truncated byte", self.pos)
}
let result = self.data[self.pos].to_int()
self.pos += 1
result
}
///|
fn Reader::take(self : Reader, n : Int32) -> Bytes raise BacnetError {
if n < 0 || n > self.remaining() {
raise Invalid("truncated payload", self.pos)
}
let result = self.data[self.pos:self.pos + n].to_owned()
self.pos += n
result
}
///|
fn Reader::uint(self : Reader, n : Int32) -> UInt32 raise BacnetError {
if n < 0 || n > 4 {
raise Invalid("integer width", self.pos)
}
let mut v = 0U
for i = 0; i < n; i = i + 1 {
v = (v << 8) | self.u8().reinterpret_as_uint()
}
v
}
///|
fn Reader::done(self : Reader) -> Unit raise BacnetError {
if self.remaining() != 0 {
raise Invalid("trailing bytes", self.pos)
}
}
///|
priv struct Writer {
bytes : Array[Byte]
maximum : Int32
}
///|
fn Writer::new(maximum : Int32) -> Writer {
{ bytes: [], maximum, }
}
///|
fn Writer::u8(self : Writer, value : Int32) -> Unit raise BacnetError {
require_range(value, 0, 255, "octet")
if self.bytes.length() >= self.maximum {
raise Limit("output bytes")
}
self.bytes.push(value.to_byte())
}
///|
fn Writer::uint(
self : Writer,
value : UInt32,
n : Int32,
) -> Unit raise BacnetError {
for i = n - 1; i >= 0; i = i - 1 {
self.u8(((value >> (i * 8)) & 255U).reinterpret_as_int())
}
}
///|
fn Writer::put(self : Writer, bytes : Bytes) -> Unit raise BacnetError {
if bytes.length() > self.maximum - self.bytes.length() {
raise Limit("output bytes")
}
for b in bytes {
self.bytes.push(b)
}
}
///|
fn Writer::finish(self : Writer) -> Bytes {
Bytes::from_array(self.bytes)
}
///|
fn unsigned_bytes(value : UInt32) -> Bytes raise BacnetError {
let n = if value <= 255U {
1
} else if value <= 65535U {
2
} else if value <= 16777215U {
3
} else {
4
}
let w = Writer::new(4)
w.uint(value, n)
w.finish()
}
///|
fn signed_bytes(value : Int32) -> Bytes raise BacnetError {
let n = if value >= -128 && value <= 127 {
1
} else if value >= -32768 && value <= 32767 {
2
} else if value >= -8388608 && value <= 8388607 {
3
} else {
4
}
let w = Writer::new(4)
w.uint(value.reinterpret_as_uint(), n)
w.finish()
}
///|
fn read_unsigned(data : Bytes) -> UInt32 raise BacnetError {
if data.length() < 1 || data.length() > 4 {
raise Invalid("unsigned width", 0)
}
Reader::new(data, Limits::default()).uint(data.length())
}
///|
fn read_signed(data : Bytes) -> Int32 raise BacnetError {
let value = read_unsigned(data)
let shift = (4 - data.length()) * 8
(value << shift).reinterpret_as_int() >> shift
}