Sign in

    fmt

    A destination passing style formatting library for MoonBit

    formatting
    string
    display
    print
    Download zip
    Version
    0.4.1
    License
    Apache-2.0
    Last updated
    11 months ago
    Downloads
    51

    No dependencies

    #illusory0x0/fmt

    A destination-passing style formatting library for MoonBit with extensible API design and efficient memory management.

    #Quick Start

    The core API revolves around the @fmt.Format trait, with helper functions @fmt.format_count and @fmt.format_write:

    ///|
    test "basic formatting" {
    let fmt = b"hello {}!"
    let data : Array[&@fmt.Format] = [b"moonbit"]
    let cnt = @fmt.format_count(fmt, data)
    let buf = @fmt.Memory::make(cnt, 0)
    let ofs = @fmt.format_write(fmt, data, buf, 0)
    inspect(string_of_memory(buf, ofs), content="hello moonbit!")
    }

    #Custom Formatters

    Implement the @fmt.Format trait for your types:

    ///|
    struct Point {
    x : Int
    y : Int
    }

    ///|
    impl @fmt.Format for Point with count(self) {
    try! @fmt.format_count(b"({}, {})", [self.x, self.y])
    }

    ///|
    impl @fmt.Format for Point with write(self, buf, start) {
    try! @fmt.format_write(b"({}, {})", [self.x, self.y], buf, start)
    }

    ///|
    test "custom formatter" {
    let p = Point::{ x: 10, y: 20 }
    let cnt = @fmt.count(p)
    let buf = @fmt.Memory::make(cnt, 0)
    let ofs = @fmt.write(p, buf, 0)
    inspect(string_of_memory(buf, ofs), content="(10, 20)")
    }

    #Formatting Manipulators

    #Number Formatting

    ///|
    test "hex formatting" {
    // Allocate a large buffer (1024 bytes) that can be reused for multiple operations
    // This avoids repeated memory allocation and is more efficient
    let buf = @fmt.Memory::make(1024, 0)
    let value = 255

    // Hex lowercase formatting
    let ofs1 = @fmt.write(@fmt.hex_lower(value), buf, 0)
    inspect(string_of_memory(buf, ofs1), content="ff")

    // Hex uppercase formatting - reuse the same buffer
    let ofs2 = @fmt.write(@fmt.hex_upper(value), buf, 0)
    inspect(string_of_memory(buf, ofs2), content="FF")
    }

    ///|
    test "endianness formatting" {
    // Use a large reusable buffer (1024 bytes) for efficiency
    let buf = @fmt.Memory::make(1024, 0)
    let value : Int = 0x12345678

    // Big-endian: most significant byte first
    let be_ofs = @fmt.write(@fmt.big_endian(value), buf, 0)
    inspect(
    bytes_of_memory(buf, be_ofs),
    content=(
    #|b"\x124Vx"
    ),
    )

    // Little-endian: least significant byte first - reuse buffer
    let le_ofs = @fmt.write(@fmt.little_endian(value), buf, 0)
    inspect(
    bytes_of_memory(buf, le_ofs),
    content=(
    #|b"xV4\x12"
    ),
    )
    }

    #Padding

    ///|
    test "padding examples" {
    // Use a large reusable buffer (1024 bytes) to avoid multiple allocations
    // More efficient than allocating separate buffers for each operation
    let buf = @fmt.Memory::make(1024, 0)
    let text = b"hello"

    // Left padding: text is right-aligned, padding on the left
    let left_ofs = @fmt.write(
    @fmt.padding_left(text, width=10, padding=' '),
    buf,
    0,
    )
    inspect(string_of_memory(buf, left_ofs), content=" hello")

    // Right padding: text is left-aligned, padding on the right - reuse buffer
    let right_ofs = @fmt.write(
    @fmt.padding_right(text, width=10, padding='*'),
    buf,
    0,
    )
    inspect(string_of_memory(buf, right_ofs), content="hello*****")

    // Center padding: text is centered - reuse buffer
    let center_ofs = @fmt.write(
    @fmt.padding_center(text, width=11, padding='-'),
    buf,
    0,
    )
    inspect(string_of_memory(buf, center_ofs), content="---hello---")
    }

    #Combining Manipulators

    ///|
    test "combined formatting" {
    // Use a large reusable buffer (1024 bytes) for efficiency
    let buf = @fmt.Memory::make(1024, 0)
    let number = 42

    // Hex + right padding: "2A" with zeros on the right
    let hex_padded = @fmt.padding_right(
    @fmt.hex_upper(number),
    width=8,
    padding='0',
    )
    let ofs = @fmt.write(hex_padded, buf, 0)
    inspect(string_of_memory(buf, ofs), content="2A000000")
    }

    #Helper Functions

    ///|
    /// Convert memory buffer to string with C-style escape sequences
    fn string_of_memory(mem : @fmt.Memory, len : Int) -> String {
    ascii_string_of_bytesview(bytes_of_memory(mem, len))
    }

    ///|
    /// Convert memory buffer to bytes
    fn bytes_of_memory(mem : @fmt.Memory, len : Int) -> Bytes {
    Bytes::makei(len, i => mem[i])
    }

    ///|
    /// C-style string escaping for debugging/logging
    pub fn ascii_string_of_bytesview(data : BytesView) -> String {
    let buffer = StringBuilder::new(size_hint=data.length() * 2)
    for b in data {
    match b {
    '\\' => buffer.write_string("\\\\")
    '\n' => buffer.write_string("\\n")
    '\r' => buffer.write_string("\\r")
    '\t' => buffer.write_string("\\t")
    '\b' => buffer.write_string("\\b")
    '\x0c' => buffer.write_string("\\f")
    c if c.to_int() < 32 || c.to_int() > 126 => {
    let code = c.to_int()
    buffer.write_string("\\")
    buffer.write_string((code / 64).to_string())
    buffer.write_string((code % 64 / 8).to_string())
    buffer.write_string((code % 8).to_string())
    }
    c => buffer.write_char(c.to_char())
    }
    }
    buffer.to_string()
    }

    Format

    if contract is violated, behavior is undefined

    big_endian

    fn[T] big_endian(x : T) ->
    BigEndian
    [T]

    count

    fn[T :
    Format
    ] count(value : T) -> Int

    format_count

    fn format_count(format : Bytes, data : Array[&
    Format
    ]) -> Int raise

    Returns the upper bound on the number of bytes that format_write would write.

    Use this function to determine buffer size before calling format_write with the same arguments. The actual bytes written by format_write will never exceed this count.

    format_write

    fn format_write(format : Bytes, data : Array[&
    Format
    ], buffer :
    Memory
    , start : Int) -> Int raise

    hex_lower

    fn[T] hex_lower(x : T) ->
    HexLower
    [T]

    hex_upper

    fn[T] hex_upper(x : T) ->
    HexUpper
    [T]

    little_endian

    fn[T] little_endian(x : T) ->
    LittleEndian
    [T]

    padding_center

    fn[T] padding_center(x : T, width~ : Int, padding~ : Byte) ->
    Center
    [T]

    padding_left

    fn[T] padding_left(x : T, width~ : Int, padding~ : Byte) ->
    Left
    [T]

    padding_right

    fn[T] padding_right(x : T, width~ : Int, padding~ : Byte) ->
    Right
    [T]

    write

    fn[T :
    Format
    ] write(value : T, buffer :
    Memory
    , start : Int) -> Int

    Source Files

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io