test "basic formatting" {
let buffer = Array::make(1024, Byte::default())
fn str(fmt : Bytes, data : Array[&Format]) -> String raise {
@fmt.write(buffer, fmt, data) |> ascii_bytes_to_string_helper
}
inspect(try? str(b"hello {} world", [123]), content="Ok(\"hello 123 world\")")
}
fn ascii_bytes_to_string_helper(avb : ArrayView[Byte]) -> String {
let buf = StringBuilder::new()
for b in avb {
buf.write_char(b.to_char())
}
buf.to_string()
}test "count allocation" {
let value = 12345
let buffer_size = Format::count(value)
let buffer = Array::make(buffer_size, Byte::default())
let written = Format::write(value, buffer)
inspect(written <= buffer_size, content="true")
}test "write with return size" {
let buffer = Array::make(10, Byte::default())
let written = Format::write(42, buffer)
inspect(written, content="2") // "42" uses 2 bytes
}pub(all) struct BigEndian[T](T)
pub(open) trait BigEndianFormat {
/// The number of bytes written must not exceed count().
write(Self, ArrayView[Byte]) -> Int
/// Upper bound on the number of bytes written
count(Self) -> Int
}
pub impl[T : BigEndianFormat] Format for BigEndian[T] with write(value, buffer) {
T::write(value.inner(), buffer)
}
pub impl[T : BigEndianFormat] Format for BigEndian[T] with count(self) {
T::count(self.inner())
}pub(open) trait Format {
/// The number of bytes written must not exceed count().
write(Self, ArrayView[Byte]) -> Int
/// Upper bound on the number of bytes written
count(Self) -> Int
}pub fn write(
buffer : ArrayView[Byte],
format : Bytes,
data : Array[&Format],
) -> ArrayView[Byte] raisetest "string interpolation" {
let buffer = Array::make(1024, Byte::default())
fn str(fmt : Bytes, data : Array[&Format]) -> String raise {
@fmt.write(buffer, fmt, data) |> ascii_bytes_to_string_helper
}
inspect(
try? str(b"Value: {}, Count: {}", [42, 10]),
content="Ok(\"Value: 42, Count: 10\")",
)
}test "endianness formatting" {
let buffer = Array::make(8, Byte::default())
let big_endian_int = @fmt.BigEndian(0x80818283)
let written = Format::write(big_endian_int, buffer)
inspect(written, content="4")
// Buffer now contains [0x80, 0x81, 0x82, 0x83]
}struct Point {
x : Int
y : Int
}
impl Format for Point with write(self, buf) {
let mut offset = 0
buf[offset] = '('
offset += 1
offset += Format::write(self.y, buf[offset:])
buf[offset] = ','
offset += 1
offset += Format::write(self.x, buf[offset:])
buf[offset] = ')'
offset += 1
offset
}
impl Format for Point with count(self) {
3 + Format::count(self.x) + Format::count(self.y)
}
test {
let point = Point:: { x: 1, y: 2 };
let buffer = Array::make(1024, Byte::default());
fn str(fmt : Bytes, data : Array[&Format]) -> String raise {
@fmt.write(buffer, fmt, data) |> ascii_bytes_to_string_helper
}
inspect(try? str("{}",[point]), content=(#|Ok("(2,1)")
))
}
suberror DebugError String derive(Show)pub(all) type BigEndian[T] Tpub(all) type LittleEndian[T] Timpl Format for LittleEndian[T]