///|
/// Bounded binary reader used by protocol codecs.
pub struct WireReader {
input : BytesView
mut offset : Int
limits : Limits
}
///|
pub fn WireReader::new(
input : BytesView,
limits : Limits,
) -> Result[WireReader, MoonLoomError] {
match limits.check_input("wire input", input.length()) {
Ok(_) => Ok({ input, offset: 0, limits, })
Err(err) => Err(err)
}
}
///|
pub fn WireReader::position(self : WireReader) -> Int {
self.offset
}
///|
pub fn WireReader::remaining(self : WireReader) -> Int {
self.input.length() - self.offset
}
///|
pub fn WireReader::is_done(self : WireReader) -> Bool {
self.offset >= self.input.length()
}
///|
pub fn WireReader::remaining_view(self : WireReader) -> BytesView {
self.input[self.offset:]
}
///|
pub fn WireReader::read_fixed(
self : WireReader,
context : String,
length : Int,
) -> Result[BytesView, MoonLoomError] {
if length < 0 {
return Err(OffsetOutOfBounds(length))
}
if self.offset + length > self.input.length() {
Err(Truncated(context, self.offset))
} else {
let result = self.input[self.offset:self.offset + length]
self.offset += length
Ok(result)
}
}
///|
pub fn WireReader::read_varint(
self : WireReader,
context : String,
) -> Result[UInt64, MoonLoomError] {
let base = self.offset
match decode_u64_with_limits(self.input[self.offset:], self.limits) {
Ok((value, consumed)) => {
self.offset += consumed
Ok(value)
}
Err(Truncated(_, offset)) => Err(Truncated(context, base + offset))
Err(InvalidVarint(_, offset)) => Err(InvalidVarint(context, base + offset))
Err(NonCanonicalVarint(offset)) => Err(NonCanonicalVarint(base + offset))
Err(err) => Err(err)
}
}
///|
pub fn WireReader::read_length_prefixed(
self : WireReader,
context : String,
) -> Result[BytesView, MoonLoomError] {
match self.read_varint(context) {
Ok(length) =>
if length > self.limits.max_input_bytes().to_uint64() {
Err(
InputTooLong(context, self.limits.max_input_bytes(), length.to_int()),
)
} else {
self.read_fixed(context, length.to_int())
}
Err(err) => Err(err)
}
}
///|
pub fn WireReader::read_u16_be(
self : WireReader,
context : String,
) -> Result[Int, MoonLoomError] {
match self.read_fixed(context, 2) {
Ok(bytes) => Ok((bytes[0].to_int() << 8) | bytes[1].to_int())
Err(err) => Err(err)
}
}
///|
/// Append-only binary writer used by protocol codecs.
pub struct WireWriter {
buffer : @buffer.Buffer
}
///|
pub fn WireWriter::new() -> WireWriter {
{ buffer: @buffer.Buffer(), }
}
///|
pub fn WireWriter::length(self : WireWriter) -> Int {
self.buffer.length()
}
///|
pub fn WireWriter::write_byte(self : WireWriter, value : Byte) -> Unit {
self.buffer.write_byte(value)
}
///|
pub fn WireWriter::write_bytes(self : WireWriter, value : BytesView) -> Unit {
for byte in value {
self.buffer.write_byte(byte)
}
}
///|
pub fn WireWriter::write_varint(self : WireWriter, value : UInt64) -> Unit {
self.write_bytes(encode_u64(value))
}
///|
pub fn WireWriter::write_u16_be(self : WireWriter, value : Int) -> Unit {
self.buffer.write_byte((value >> 8).to_byte())
self.buffer.write_byte((value & 0xFF).to_byte())
}
///|
pub fn WireWriter::write_length_prefixed(
self : WireWriter,
value : BytesView,
) -> Unit {
self.write_varint(value.length().to_uint64())
self.write_bytes(value)
}
///|
pub fn WireWriter::to_bytes(self : WireWriter) -> Bytes {
self.buffer.to_bytes()
}