Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/internal/c_buffer/README.mbt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# internal/c_buffer

Internal wrapper for C-allocated byte buffers.

## Overview

`@internal/c_buffer` exposes an opaque `Buffer` type and a small set of
FFI-backed helpers used throughout the async runtime. These APIs are unsafe:
they operate on raw pointers and assume correct size, lifetime, and
null-termination guarantees from native code.

This package is **native-only**. The JavaScript backend is not supported.

## API Summary

- `Buffer`: opaque C pointer
- `blit_from_bytes`: copy MoonBit `Bytes` into a C buffer
- `blit_to_bytes`: copy C buffer content into a MoonBit `FixedArray[Byte]`
- `get`: read a single byte by index
- `strlen`: length of a NUL-terminated C string
- `null`, `is_null`, `free`

## Safety and Ownership

- `Buffer` values are raw pointers; no bounds checks are performed.
- `free` must only be called on memory allocated by `malloc` or a compatible
allocator. Passing `null` is allowed.
- `strlen` requires a valid NUL-terminated sequence.

## Examples

```mbt check
///|
#cfg(not(target="js"))
test "null helpers" {
inspect(@c_buffer.Buffer::is_null(@c_buffer.null), content="true")
@c_buffer.Buffer::free(@c_buffer.null)
}
```
58 changes: 58 additions & 0 deletions src/internal/c_buffer/c_buffer.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,31 @@
// limitations under the License.

///|
/// Opaque handle to a native C buffer.
///
/// `Buffer` represents a raw pointer managed by native code. All functions in
/// this package assume the pointer is valid and sized appropriately. It is an
/// internal FFI helper, not a general-purpose memory container.
///
/// # Example
/// ```mbt nocheck
/// test {
/// let ptr : Buffer = null
/// inspect(Buffer::is_null(ptr), content="true")
/// }
/// ```
#external
pub type Buffer

///|
/// Copy bytes from a MoonBit `Bytes` into a C buffer.
///
/// `offset` and `len` select a range within `src`. The destination buffer must
/// have at least `len` bytes available.
///
/// # Safety
/// `dst` must be a valid writable buffer; `src` must be valid for the requested
/// range.
#borrow(src)
pub extern "C" fn Buffer::blit_from_bytes(
dst : Buffer,
Expand All @@ -26,6 +47,13 @@ pub extern "C" fn Buffer::blit_from_bytes(
) = "moonbitlang_async_blit_to_c"

///|
/// Copy bytes from a C buffer into a MoonBit fixed array.
///
/// The destination array must have enough room for `len` bytes starting at
/// `offset`.
///
/// # Safety
/// `src` must be a valid readable buffer containing at least `len` bytes.
#borrow(dst)
pub extern "C" fn Buffer::blit_to_bytes(
src : Buffer,
Expand All @@ -35,21 +63,51 @@ pub extern "C" fn Buffer::blit_to_bytes(
) = "moonbitlang_async_blit_from_c"

///|
/// Read a single byte from the buffer at `index`.
///
/// # Safety
/// `buf` must be valid and the index must be within bounds of the allocated
/// buffer.
#borrow(buf)
#alias("_[_]")
pub extern "C" fn Buffer::get(buf : Buffer, index : Int) -> Byte = "moonbitlang_async_c_buffer_get"

///|
/// Measure the length of a NUL-terminated C string.
///
/// # Safety
/// `buf` must point to a valid NUL-terminated byte sequence.
pub extern "C" fn Buffer::strlen(buf : Buffer) -> Int = "moonbitlang_async_strlen"

///|
extern "C" fn Buffer::null() -> Buffer = "moonbitlang_async_null_pointer"

///|
/// A null C pointer for use with `Buffer`.
///
/// # Example
/// ```mbt nocheck
/// test {
/// inspect(Buffer::is_null(null), content="true")
/// Buffer::free(null)
/// }
/// ```
pub let null : Buffer = Buffer::null()

///|
/// Check whether the pointer is null.
///
/// # Example
/// ```mbt nocheck
/// test {
/// let ptr = null
/// inspect(Buffer::is_null(ptr), content="true")
/// }
/// ```
pub extern "C" fn Buffer::is_null(ptr : Buffer) -> Bool = "moonbitlang_async_pointer_is_null"

///|
/// Free a C buffer allocated with `malloc` or compatible APIs.
///
/// Passing `null` is allowed and has no effect.
pub extern "C" fn Buffer::free(buf : Buffer) = "free"
Loading