Skip to content
Merged
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
4 changes: 2 additions & 2 deletions example/font/main.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub fn render() -> Unit {
///|
/// Example implementation of drawing text with a drop shadow
fn draw_text_shadow(
text : Bytes,
text : BytesView,
font : @firefly.Font,
point : Point,
text_color : Color,
Expand All @@ -83,7 +83,7 @@ fn draw_text_shadow(
///|
/// Example implementation of drawing text with a drop shadow
fn draw_text_rainbow(
text : Bytes,
text : BytesView,
font : @firefly.Font,
point : Point,
text_colors? : FixedArray[Color] = [
Expand Down
16 changes: 8 additions & 8 deletions example/random/main.mbt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
///|
using @firefly {type Style, type Point}
using @firefly {type Style, type Point, type Utf8}

///|
fn main {
Expand All @@ -9,12 +9,12 @@ fn main {
///|
/// boot is only called once, after all the memory is initialized.
pub fn boot() -> Unit {
@firefly.log_debug("random float: " + format(@random.float()))
@firefly.log_debug("random double: " + format(@random.double()))
@firefly.log_debug("random int: " + format(@random.int()))
@firefly.log_debug("random uint: " + format(@random.uint()))
@firefly.log_debug("random int64: " + format(@random.int64()))
@firefly.log_debug("random uint64: " + format(@random.uint64()))
@firefly.log_debug(("random float: " : Utf8) + format(@random.float()))
@firefly.log_debug(("random double: " : Utf8) + format(@random.double()))
@firefly.log_debug(("random int: " : Utf8) + format(@random.int()))
@firefly.log_debug(("random uint: " : Utf8) + format(@random.uint()))
@firefly.log_debug(("random int64: " : Utf8) + format(@random.int64()))
@firefly.log_debug(("random uint64: " : Utf8) + format(@random.uint64()))
let colors : FixedArray[@firefly.Color] = [
Red,
Orange,
Expand Down Expand Up @@ -57,6 +57,6 @@ pub fn render() -> Unit {
}

///|
fn[T : Show] format(v : T) -> Bytes {
fn[T : Show] format(v : T) -> Utf8 {
@utf8.encode(v.to_string())
}
1 change: 1 addition & 0 deletions src/audio/moon.pkg
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
"firefly/firefly",
"firefly/firefly/internal/ffi",
"firefly/firefly/internal/memory",
}
6 changes: 3 additions & 3 deletions src/audio/node.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -310,12 +310,12 @@ pub fn Node::add_zero(self : Node) -> Zero {

///|
/// Add source playing audio from a file.
pub fn Node::add_file(self : Node, path : Bytes) -> File {
pub fn Node::add_file(self : Node, path : @firefly.Utf8View) -> File {
let file = File(Node::{
id: @ffi.audio_add_file(
self.id,
@memory.bytes_addr(path),
@memory.bytes_size(path),
@memory.bytesview_addr(path),
@memory.bytesview_size(path),
),
})
@memory.keep(path)
Expand Down
38 changes: 21 additions & 17 deletions src/fs.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,25 @@
/// Firefly Zero runtime enforces flat structure for app data and ROMs,
/// so the path cannot contain path separators (`/`).
///
/// Must be UTF-8 encoded.
/// Any String literal or Bytes literal is a valid ASCII string:
///
/// ```text
/// @firefly.load_file("font")
/// ```
pub type Path = Bytes

///|
pub type PathView = BytesView

///|
/// Get size (in bytes) of a file from ROM or the data directory.
///
/// Returns 0 if the file does not exist.
pub fn get_file_size(path : Path) -> Int {
pub fn get_file_size(path : PathView) -> Int {
let size = @ffi.get_file_size(
@memory.bytes_addr(path),
@memory.bytes_size(path),
@memory.bytesview_addr(path),
@memory.bytesview_size(path),
)
@memory.keep(path)
size
Expand All @@ -27,24 +31,24 @@ pub fn get_file_size(path : Path) -> Int {
///|
/// Check if the given path points to a file in ROM or the data directory.
#inline
pub fn is_file(path : Path) -> Bool {
pub fn is_file(path : PathView) -> Bool {
get_file_size(path) != 0
}

///|
/// Load a file from ROM or the data directory.
///
/// Example: loading fonts, images, or save files.
pub fn load_file(path : Path) -> File? {
pub fn load_file(path : PathView) -> File? {
let size = @ffi.get_file_size(
@memory.bytes_addr(path),
@memory.bytes_size(path),
@memory.bytesview_addr(path),
@memory.bytesview_size(path),
)
guard size != 0 else { None }
let buf = FixedArray::make(size, Byte::default())
let _ = @ffi.load_file(
@memory.bytes_addr(path),
@memory.bytes_size(path),
@memory.bytesview_addr(path),
@memory.bytesview_size(path),
@memory.fixedbytes_addr(buf),
@memory.fixedbytes_size(buf),
)
Expand All @@ -58,10 +62,10 @@ pub fn load_file(path : Path) -> File? {
/// Returns the number of bytes that has been loaded.
///
/// Example: loading fonts, images, or save files.
pub fn load_file_to(path : Path, output : FixedArray[Byte]) -> Int {
pub fn load_file_to(path : PathView, output : FixedArray[Byte]) -> Int {
let size = @ffi.load_file(
@memory.bytes_addr(path),
@memory.bytes_size(path),
@memory.bytesview_addr(path),
@memory.bytesview_size(path),
@memory.fixedbytes_addr(output),
@memory.fixedbytes_size(output),
)
Expand All @@ -78,10 +82,10 @@ pub fn load_file_to(path : Path, output : FixedArray[Byte]) -> Int {
/// Example: writing save files.
///
/// Returns the number of bytes written.
pub fn dump_file(path : Path, file : File) -> Int {
pub fn dump_file(path : PathView, file : File) -> Int {
let size = @ffi.load_file(
@memory.bytes_addr(path),
@memory.bytes_size(path),
@memory.bytesview_addr(path),
@memory.bytesview_size(path),
@memory.fixedbytes_addr(file.0),
@memory.fixedbytes_size(file.0),
)
Expand All @@ -93,7 +97,7 @@ pub fn dump_file(path : Path, file : File) -> Int {
/// Removes a file (if exists) from the data directory.
///
/// Example: removing save files.
pub fn remove_file(path : Path) -> Unit {
@ffi.remove_file(@memory.bytes_addr(path), @memory.bytes_size(path))
pub fn remove_file(path : PathView) -> Unit {
@ffi.remove_file(@memory.bytesview_addr(path), @memory.bytesview_size(path))
@memory.keep(path)
}
4 changes: 2 additions & 2 deletions src/fs_file.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub fn File::as_fixed_array(self : File) -> FixedArray[Byte] {
///
/// Example: loading fonts, images, or save files.
#inline
pub fn File::load(path : Bytes) -> File? {
pub fn File::load(path : PathView) -> File? {
load_file(path)
}

Expand All @@ -53,6 +53,6 @@ pub fn File::load(path : Bytes) -> File? {
///
/// Returns the number of bytes written.
#inline
pub fn File::dump(self : File, path : Bytes) -> Int {
pub fn File::dump(self : File, path : PathView) -> Int {
dump_file(path, self)
}
12 changes: 6 additions & 6 deletions src/graphics.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,14 @@ pub fn draw_sector(
/// ignore(utf8)
/// ```
pub fn draw_text(
text : Bytes,
text : Utf8View,
font : Font,
point : Point,
color : Color,
) -> Unit {
@ffi.draw_text(
@memory.bytes_addr(text),
@memory.bytes_size(text),
@memory.bytesview_addr(text),
@memory.bytesview_size(text),
@memory.fixedbytes_addr(font.0),
@memory.fixedbytes_size(font.0),
point.x,
Expand All @@ -218,14 +218,14 @@ pub fn draw_text(
///|
/// Render a QR-code.
pub fn draw_qr(
text : Bytes,
text : Utf8View,
point : Point,
black : Color,
white : Color,
) -> Unit {
@ffi.draw_qr(
@memory.bytes_addr(text),
@memory.bytes_size(text),
@memory.bytesview_addr(text),
@memory.bytesview_size(text),
point.x,
point.y,
black.to_int(),
Expand Down
16 changes: 13 additions & 3 deletions src/internal/memory/memory.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
/// before Firefly runtime consumes it. To prevent this, call "keep"
/// at the end of the function to keep the value from being deallocated too early.
#inline
pub fn[T] keep(v : T) -> Unit {
ignore(v)
}
pub fn[T] keep(v : T) -> Unit = "%ignore"

///|
#inline
Expand All @@ -21,6 +19,12 @@ pub fn bytes_size(bytes : Bytes) -> Int {
bytes.length()
}

///|
#inline
pub fn bytesview_size(bytes : BytesView) -> Int {
bytes.length()
}

///|
#inline
#borrow(bytes)
Expand All @@ -34,3 +38,9 @@ pub extern "wasm" fn fixedbytes_addr(bytes : FixedArray[Byte]) -> UInt =
pub extern "wasm" fn bytes_addr(bytes : Bytes) -> UInt =
#|(func (param i32) (result i32)
#| (i32.add (local.get 0) (i32.const 8)))

///|
#inline
pub fn bytesview_addr(bytes : BytesView) -> UInt {
bytes_addr(bytes.data()) + bytes.start_offset().reinterpret_as_uint()
}
47 changes: 42 additions & 5 deletions src/misc.mbt
Original file line number Diff line number Diff line change
@@ -1,14 +1,51 @@
///|
/// Type hint that we need a UTF-8 formatted `Bytes`.
///
/// All Firefly functions that accept text only accepts UTF-8 encoded text.
/// But MoonBit uses UTF-16 for its `string` type.
/// Meaning, you should not be using the MoonBit `string` type with the Firefly SDK.
///
/// Instead, you can use string and bytes literals with `Utf8` (or `Bytes`)
///
/// ```mbt check
/// test {
/// let utf8 : @firefly.Utf8 = "hello"
/// ignore(utf8)
/// }
/// ```
pub type Utf8 = Bytes

///|
/// Type hint that we need a UTF-8 formatted `BytesView`.
///
/// A "view" is a reference to a part of a `Bytes`, and is more flexible
/// to use as function parameters.
///
/// All Firefly functions that accept text only accepts UTF-8 encoded text.
/// But MoonBit uses UTF-16 for its `string` type.
/// Meaning, you should not be using the MoonBit `string` type with the Firefly SDK.
///
/// Instead, you can use string and bytes literals with `Utf8View` (or `BytesView`)
///
/// ```mbt check
/// test {
/// let utf8 : @firefly.Utf8View = "hello"
/// ignore(utf8)
/// }
/// ```
pub type Utf8View = BytesView

///|
/// Log a debug message.
pub fn log_debug(s : Bytes) -> Unit {
@ffi.log_debug(@memory.bytes_addr(s), @memory.bytes_size(s))
pub fn log_debug(s : Utf8View) -> Unit {
@ffi.log_debug(@memory.bytesview_addr(s), @memory.bytesview_size(s))
@memory.keep(s)
}

///|
/// Log an error message.
pub fn log_error(s : Bytes) -> Unit {
@ffi.log_error(@memory.bytes_addr(s), @memory.bytes_size(s))
pub fn log_error(s : Utf8View) -> Unit {
@ffi.log_error(@memory.bytesview_addr(s), @memory.bytesview_size(s))
@memory.keep(s)
}

Expand Down Expand Up @@ -41,7 +78,7 @@ pub fn get_random() -> UInt {

///|
/// Get name of the device.
pub fn get_name(peer : Peer) -> Bytes {
pub fn get_name(peer : Peer) -> Utf8 {
let arr = FixedArray::make(16, Byte::default())
let len = @ffi.get_name(peer.raw, @memory.fixedbytes_addr(arr))
Bytes::from_array(arr[:len])
Expand Down
10 changes: 5 additions & 5 deletions src/misc_language.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub fn Language::from_raw(raw : UInt16) -> Language? {
}

///|
pub fn Language::from_code(code : Bytes) -> Language? {
pub fn Language::from_code(code : Utf8View) -> Language? {
match code {
"en" => Some(English)
"nl" => Some(Dutch)
Expand All @@ -75,7 +75,7 @@ pub fn Language::from_code(code : Bytes) -> Language? {

///|
/// The language name in English.
pub fn Language::name_english(lang : Language) -> Bytes {
pub fn Language::name_english(lang : Language) -> Utf8 {
match lang {
English => "English"
Dutch => "Dutch"
Expand All @@ -95,7 +95,7 @@ pub fn Language::name_english(lang : Language) -> Bytes {

///|
/// The language name in the language itself (endonym).
pub fn Language::name_native(lang : Language) -> Bytes {
pub fn Language::name_native(lang : Language) -> Utf8 {
match lang {
English => "English"
Dutch => "Nederlands"
Expand All @@ -114,7 +114,7 @@ pub fn Language::name_native(lang : Language) -> Bytes {
}

///|
pub fn Language::code(lang : Language) -> Bytes {
pub fn Language::code(lang : Language) -> Utf8 {
match lang {
English => "en"
Dutch => "nl"
Expand All @@ -136,7 +136,7 @@ pub fn Language::code(lang : Language) -> Bytes {
/// ISO 8859 encoding slug for the language.
///
/// Useful for dynamically loading the correct font for the given language.
pub fn Language::encoding(lang : Language) -> Bytes {
pub fn Language::encoding(lang : Language) -> Utf8 {
match lang {
// Just like English, Dutch has very little non-ASCII characters
// which can be avoided in translations to make it possible to stick
Expand Down