#bytes

    This package provides utilities for working with sequences of bytes, offering both an owned representation (Bytes) and a slice representation (BytesView); both are immutable.

    #Creating Bytes

    You can create Bytes from various sources including arrays, fixed arrays, and iterators:

    ///|
    test "bytes creation" {
    // Create from array of bytes
    let arr = [b'h', b'e', b'l', b'l', b'o']
    let bytes1 = Bytes::from_array(arr)
    inspect(
    bytes1,
    content=(
    #|b"hello"
    ),
    )

    // Create from fixed array
    let fixed = FixedArray::make(3, b'a')
    let bytes2 = Bytes::from_array(fixed)
    inspect(
    bytes2,
    content=(
    #|b"aaa"
    ),
    )

    // Create empty bytes
    let empty = (Default::default() : Bytes)
    inspect(
    empty,
    content=(
    #|b""
    ),
    )

    // Create from iterator
    let iter_bytes = Bytes::from_iter(arr.iter())
    inspect(
    iter_bytes,
    content=(
    #|b"hello"
    ),
    )
    }

    #Converting Between Formats

    Bytes can be converted to and from different formats:

    ///|
    test "bytes conversion" {
    let original : ReadOnlyArray[Byte] = [b'x', b'y', b'z']
    let bytes = Bytes::from_array(original)

    // Convert to array
    let array = bytes.to_array()
    debug_inspect(
    array,
    content=(
    #|[0x78, 0x79, 0x7a]
    ),
    )

    // Convert to fixed array
    let fixed = bytes.to_fixedarray()
    debug_inspect(
    fixed,
    content=(
    #|<FixedArray: [0x78, 0x79, 0x7a]>
    ),
    )

    // Convert to iterator and collect back
    let collected = bytes.iter().to_array()
    debug_inspect(
    collected,
    content=(
    #|[0x78, 0x79, 0x7a]
    ),
    )
    }

    #Working with Views

    Use bytes.exact_view(start~, end~) to validate bounds, bytes.get_view(start~, end~) to return None for invalid bounds, or bytes.clamped_view(start~, end~) to clamp them. These methods are also available on BytesView. The old view and sub names are deprecated in favor of exact_view.

    Views provide a way to work with portions of bytes and interpret them as various numeric types:

    For Bytes and BytesView, bytes[start:end] clamps each bound to the current length, treats negative bounds as zero, and returns an empty view for an inverted range. Omitted bounds select the corresponding end of the bytes or view. Use bytes.exact_view(start~, end~) to require valid bounds, or bytes.get_view(start~, end~) to return None for an invalid range.

    ///|
    test "bytes view operations" {
    // Create bytes with numeric data
    let num_bytes = Bytes::from_array([0x12, 0x34, 0x56, 0x78])

    // Create a view
    let view = num_bytes[:]

    // Get individual bytes
    inspect(view[0], content="b'\\x12'")

    // Interpret as integers (big-endian)
    guard view is [i32be(x), ..] else {
    fail("Failed to match big-endian integer pattern")
    }
    inspect(x, content="305419896")

    // Interpret as integers (little-endian)
    guard view is [i32le(y), ..] else {
    fail("Failed to match little-endian integer pattern")
    }
    inspect(y, content="2018915346")

    // Create a sub-view
    let sub_view = view[1:3]
    inspect(sub_view.length(), content="2")
    }

    #Binary Data Interpretation

    Views provide methods to interpret byte sequences as various numeric types in both little-endian and big-endian formats:

    ///|
    test "numeric interpretation" {
    // Create test data
    let int64_bytes = Bytes::from_array([
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
    ])
    guard int64_bytes is [i64be(x), ..] else {
    fail("Failed to match big-endian int64 pattern")
    }
    inspect(x, content="66")
    guard int64_bytes is [u64le(x), ..] else {
    fail("Failed to match little-endian uint64 pattern")
    }
    inspect(x, content="4755801206503243776")
    }

    #Concatenation and Comparison

    Bytes can be concatenated and compared:

    ///|
    test "bytes operations" {
    let b1 = Bytes::from_array([b'a', b'b'])
    let b2 = Bytes::from_array([b'c', b'd'])

    // Concatenation
    let combined = b1 + b2
    inspect(
    combined,
    content=(
    #|b"abcd"
    ),
    )

    // Comparison
    let same = Bytes::from_array([b'a', b'b'])
    let different = Bytes::from_array([b'x', b'y'])
    inspect(b1 == same, content="true")
    inspect(b1 == different, content="false")
    inspect(b1 < b2, content="true")
    }

    #Prefixes, Suffixes, and Chopping

    You can check for prefixes and suffixes or remove them when present:

    ///|
    test "bytes prefix/suffix" {
    let bytes = b"hello"
    inspect(bytes.has_prefix(b"he"), content="true")
    inspect(bytes.has_suffix(b"lo"), content="true")
    debug_inspect(
    bytes.chop_prefix(b"he"),
    content="Some(<BytesView: [0x6c, 0x6c, 0x6f]>)",
    )
    debug_inspect(
    bytes.chop_suffix(b"lo"),
    content="Some(<BytesView: [0x68, 0x65, 0x6c]>)",
    )
    debug_inspect(bytes.chop_prefix(b"zz"), content="None")
    }

    View

    using @moonbitlang/core/builtin { type BytesView as View }

    Type View used by this package APIs.

    Source Files