feat: lifetime elision, tooling CI, registry, and LSP locals

Ship the QUALITY_PLAN stretch from ownership through ecosystem: C.1
lifetime elision (bootstrap + selfhost), bux fmt/test/doc CI hooks,
stdlib goldens, package registry (bux search/add), and LSP 0.4
position-sensitive locals with inferred let types. Full-tree format
pass plus Map/Set remove double-free fix.
This commit is contained in:
2026-07-19 16:35:08 +03:00
parent 3eb1ad3a82
commit 53b43b0f79
130 changed files with 20494 additions and 16738 deletions
+122 -114
View File
@@ -1,135 +1,143 @@
module Std::Array {
extern func bux_alloc(size: uint) -> *void;
extern func bux_realloc(ptr: *void, size: uint) -> *void;
extern func bux_free(ptr: *void);
extern func bux_bounds_check(index: uint, len: uint);
extern func bux_alloc(size: uint) -> *void;
extern func bux_realloc(ptr: *void, size: uint) -> *void;
extern func bux_free(ptr: *void);
extern func bux_bounds_check(index: uint, len: uint);
struct Array<T> {
data: *T,
len: uint,
cap: uint,
}
/// Growable contiguous buffer of `T` (len + capacity).
struct Array<T> {
data: *T,
len: uint,
cap: uint,
}
func Array_New<T>(cap: uint) -> Array<T> {
let data = bux_alloc(cap * sizeof(T)) as *T;
return Array<T> { data: data, len: 0, cap: cap };
}
/// Create an empty array with the given initial capacity.
func Array_New<T>(cap: uint) -> Array<T> {
let data = bux_alloc(cap * sizeof(T)) as *T;
return Array<T> { data: data, len: 0, cap: cap };
}
func Array_Push<T>(self: *Array<T>, value: T) {
if self.len >= self.cap {
self.cap = self.cap * 2;
/// Append `value`, growing capacity if needed.
func Array_Push<T>(self: *Array<T>, value: T) {
if self.len >= self.cap {
self.cap = self.cap * 2;
self.data = bux_realloc(self.data as *void, self.cap * sizeof(T)) as *T;
}
self.data[self.len] = value;
self.len = self.len + 1;
}
/// Element at `index` (bounds-checked unless `@[Release]`).
func Array_Get<T>(self: *Array<T>, index: uint) -> T {
bux_bounds_check(index, self.len);
return self.data[index];
}
/// Write `value` at `index` (bounds-checked unless `@[Release]`).
func Array_Set<T>(self: *Array<T>, index: uint, value: T) {
bux_bounds_check(index, self.len);
self.data[index] = value;
}
/// Number of live elements.
func Array_Len<T>(self: *Array<T>) -> uint {
return self.len;
}
/// Free the backing buffer and reset length/capacity to zero.
func Array_Free<T>(self: *Array<T>) {
bux_free(self.data as *void);
self.data = null as *T;
self.len = 0;
self.cap = 0;
}
/// Drop trait entry — same as `Array_Free`.
func Array_Drop<T>(self: *Array<T>) {
Array_Free<T>(self);
}
func Array_operator_index_get<T>(self: *Array<T>, idx: uint) -> T {
return Array_Get<T>(self, idx);
}
func Array_operator_index_set<T>(self: *Array<T>, idx: uint, value: T) {
Array_Set<T>(self, idx, value);
}
/// True if the array has no elements.
func Array_IsEmpty<T>(self: *Array<T>) -> bool {
return self.len == 0;
}
/// Current capacity (not length).
func Array_Cap<T>(self: *Array<T>) -> uint {
return self.cap;
}
/// Drop length to zero; keeps allocated capacity.
func Array_Clear<T>(self: *Array<T>) {
self.len = 0;
}
/// Ensure capacity is at least `minCap` (does not shrink).
func Array_Reserve<T>(self: *Array<T>, minCap: uint) {
if minCap <= self.cap {
return;
}
self.cap = minCap;
self.data = bux_realloc(self.data as *void, self.cap * sizeof(T)) as *T;
}
self.data[self.len] = value;
self.len = self.len + 1;
}
func Array_Get<T>(self: *Array<T>, index: uint) -> T {
bux_bounds_check(index, self.len);
return self.data[index];
}
func Array_Set<T>(self: *Array<T>, index: uint, value: T) {
bux_bounds_check(index, self.len);
self.data[index] = value;
}
func Array_Len<T>(self: *Array<T>) -> uint {
return self.len;
}
func Array_Free<T>(self: *Array<T>) {
bux_free(self.data as *void);
self.data = null as *T;
self.len = 0;
self.cap = 0;
}
func Array_Drop<T>(self: *Array<T>) {
Array_Free<T>(self);
}
func Array_operator_index_get<T>(self: *Array<T>, idx: uint) -> T {
return Array_Get<T>(self, idx);
}
func Array_operator_index_set<T>(self: *Array<T>, idx: uint, value: T) {
Array_Set<T>(self, idx, value);
}
/* True if the array has no elements */
func Array_IsEmpty<T>(self: *Array<T>) -> bool {
return self.len == 0;
}
/* Current capacity (not length) */
func Array_Cap<T>(self: *Array<T>) -> uint {
return self.cap;
}
/* Drop length to zero; keeps allocated capacity */
func Array_Clear<T>(self: *Array<T>) {
self.len = 0;
}
/* Ensure capacity is at least minCap (does not shrink) */
func Array_Reserve<T>(self: *Array<T>, minCap: uint) {
if minCap <= self.cap {
return;
/// First element (bounds-checked if empty).
func Array_First<T>(self: *Array<T>) -> T {
return Array_Get<T>(self, 0);
}
self.cap = minCap;
self.data = bux_realloc(self.data as *void, self.cap * sizeof(T)) as *T;
}
/* First element (panics if empty via bounds check) */
func Array_First<T>(self: *Array<T>) -> T {
return Array_Get<T>(self, 0);
}
/// Last element (bounds-checked if empty).
func Array_Last<T>(self: *Array<T>) -> T {
return Array_Get<T>(self, self.len - 1);
}
/* Last element (panics if empty via bounds check) */
func Array_Last<T>(self: *Array<T>) -> T {
return Array_Get<T>(self, self.len - 1);
}
/// Remove and return the last element (bounds-checked if empty).
func Array_Pop<T>(self: *Array<T>) -> T {
bux_bounds_check(0, self.len);
self.len = self.len - 1;
return self.data[self.len];
}
/* Remove and return the last element (panics if empty) */
func Array_Pop<T>(self: *Array<T>) -> T {
bux_bounds_check(0, self.len);
self.len = self.len - 1;
return self.data[self.len];
}
/* Linear search: true if value is present (uses ==) */
func Array_Contains<T>(self: *Array<T>, value: T) -> bool {
var i: uint = 0;
while i < self.len {
if self.data[i] == value {
return true;
/// Linear search: true if `value` is present (uses `==`).
func Array_Contains<T>(self: *Array<T>, value: T) -> bool {
var i: uint = 0;
while i < self.len {
if self.data[i] == value {
return true;
}
i = i + 1;
}
i = i + 1;
return false;
}
return false;
}
/* Index of first equal element, or -1 if not found */
func Array_IndexOf<T>(self: *Array<T>, value: T) -> int {
var i: uint = 0;
while i < self.len {
if self.data[i] == value {
return i as int;
/// Index of first equal element, or `-1` if not found.
func Array_IndexOf<T>(self: *Array<T>, value: T) -> int {
var i: uint = 0;
while i < self.len {
if self.data[i] == value {
return i as int;
}
i = i + 1;
}
i = i + 1;
return -1;
}
return -1;
}
/* Append all elements of other onto self */
func Array_Extend<T>(self: *Array<T>, other: *Array<T>) {
var i: uint = 0;
while i < other.len {
Array_Push<T>(self, other.data[i]);
i = i + 1;
/// Append all elements of `other` onto `self`.
func Array_Extend<T>(self: *Array<T>, other: *Array<T>) {
var i: uint = 0;
while i < other.len {
Array_Push<T>(self, other.data[i]);
i = i + 1;
}
}
}
}
+48 -48
View File
@@ -1,64 +1,64 @@
module Std::Channel {
extern func bux_channel_new(capacity: int64, elem_size: int64) -> *void;
extern func bux_channel_send(handle: *void, elem: *void);
extern func bux_channel_recv(handle: *void, out: *void) -> int;
extern func bux_channel_close(handle: *void);
extern func bux_channel_free(handle: *void);
extern func bux_channel_new(capacity: int64, elem_size: int64) -> *void;
extern func bux_channel_send(handle: *void, elem: *void);
extern func bux_channel_recv(handle: *void, out: *void) -> int;
extern func bux_channel_close(handle: *void);
extern func bux_channel_free(handle: *void);
struct Channel<T> {
handle: *void;
}
struct Channel<T> {
handle: *void;
}
func Channel_New<T>(capacity: int64) -> Channel<T> {
return Channel<T> { handle: bux_channel_new(capacity, sizeof(T)) };
}
func Channel_New<T>(capacity: int64) -> Channel<T> {
return Channel<T> { handle: bux_channel_new(capacity, sizeof(T)) };
}
func Channel_Send<T>(ch: *Channel<T>, value: T) {
bux_channel_send(ch.handle, (&value) as *void);
}
func Channel_Send<T>(ch: *Channel<T>, value: T) {
bux_channel_send(ch.handle, (&value) as *void);
}
func Channel_Recv<T>(ch: *Channel<T>) -> T {
var result: T;
bux_channel_recv(ch.handle, (&result) as *void);
return result;
}
func Channel_Recv<T>(ch: *Channel<T>) -> T {
var result: T;
bux_channel_recv(ch.handle, (&result) as *void);
return result;
}
func Channel_Recv_Ok<T>(ch: *Channel<T>, out: *T) -> bool {
return bux_channel_recv(ch.handle, out as *void) != 0;
}
func Channel_Recv_Ok<T>(ch: *Channel<T>, out: *T) -> bool {
return bux_channel_recv(ch.handle, out as *void) != 0;
}
func Channel_Close<T>(ch: *Channel<T>) {
bux_channel_close(ch.handle);
}
func Channel_Close<T>(ch: *Channel<T>) {
bux_channel_close(ch.handle);
}
func Channel_Free<T>(ch: *Channel<T>) {
bux_channel_free(ch.handle);
}
func Channel_Free<T>(ch: *Channel<T>) {
bux_channel_free(ch.handle);
}
func Channel_Drop<T>(ch: *Channel<T>) {
Channel_Free<T>(ch);
}
func Channel_Drop<T>(ch: *Channel<T>) {
Channel_Free<T>(ch);
}
/* Convenience wrappers for common types */
func Channel_SendInt(ch: *Channel<int>, value: int) {
bux_channel_send(ch.handle, (&value) as *void);
}
/* Convenience wrappers for common types */
func Channel_SendInt(ch: *Channel<int>, value: int) {
bux_channel_send(ch.handle, (&value) as *void);
}
func Channel_RecvInt(ch: *Channel<int>) -> int {
var result: int = 0;
bux_channel_recv(ch.handle, (&result) as *void);
return result;
}
func Channel_RecvInt(ch: *Channel<int>) -> int {
var result: int = 0;
bux_channel_recv(ch.handle, (&result) as *void);
return result;
}
func Channel_SendFloat64(ch: *Channel<float64>, value: float64) {
bux_channel_send(ch.handle, (&value) as *void);
}
func Channel_SendFloat64(ch: *Channel<float64>, value: float64) {
bux_channel_send(ch.handle, (&value) as *void);
}
func Channel_RecvFloat64(ch: *Channel<float64>) -> float64 {
var result: float64 = 0.0;
bux_channel_recv(ch.handle, (&result) as *void);
return result;
}
func Channel_RecvFloat64(ch: *Channel<float64>) -> float64 {
var result: float64 = 0.0;
bux_channel_recv(ch.handle, (&result) as *void);
return result;
}
}
+61 -61
View File
@@ -10,72 +10,72 @@
// =============================================================================
module Std::Crypto {
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len};
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len};
// Re-use the same externs from submodules (merged by compiler)
extern func bux_sha256(data: String, len: int, out: *void);
extern func bux_hmac_sha256(key: String, keylen: int, msg: String, msglen: int, out: *void);
extern func bux_random_bytes(buf: *void, len: int) -> int;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_base64_decode(data: String, len: int, outlen: *int) -> String;
extern func bux_bytes_to_hex(data: *void, len: int) -> String;
// Re-use the same externs from submodules (merged by compiler)
extern func bux_sha256(data: String, len: int, out: *void);
extern func bux_hmac_sha256(key: String, keylen: int, msg: String, msglen: int, out: *void);
extern func bux_random_bytes(buf: *void, len: int) -> int;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_base64_decode(data: String, len: int, outlen: *int) -> String;
extern func bux_bytes_to_hex(data: *void, len: int) -> String;
// --- Legacy function names (delegate to new submodule functions) ---
// --- Legacy function names (delegate to new submodule functions) ---
// SHA-256 → hex
func Crypto_Sha256(data: String) -> String {
let len: int = String_Len(data) as int;
let hashBuf: *void = Alloc(32);
bux_sha256(data, len, hashBuf);
let result: String = bux_bytes_to_hex(hashBuf as *void, 32);
Free(hashBuf);
return result;
}
// HMAC-SHA256 → hex
func Crypto_HmacSha256(key: String, message: String) -> String {
let keylen: int = String_Len(key) as int;
let msglen: int = String_Len(message) as int;
let hmacBuf: *void = Alloc(32);
bux_hmac_sha256(key, keylen, message, msglen, hmacBuf);
let result: String = bux_bytes_to_hex(hmacBuf as *void, 32);
Free(hmacBuf);
return result;
}
// Random bytes → base64
func Crypto_RandomBytes(n: int) -> String {
if n <= 0 { return ""; }
let buf: *void = Alloc(n as uint);
if bux_random_bytes(buf, n) != 1 {
Free(buf);
return "";
// SHA-256 → hex
func Crypto_Sha256(data: String) -> String {
let len: int = String_Len(data) as int;
let hashBuf: *void = Alloc(32);
bux_sha256(data, len, hashBuf);
let result: String = bux_bytes_to_hex(hashBuf as *void, 32);
Free(hashBuf);
return result;
}
let result: String = bux_base64_encode(buf as String, n);
Free(buf);
return result;
}
// Base64 encode
func Crypto_Base64Encode(s: String) -> String {
return bux_base64_encode(s, String_Len(s) as int);
}
// HMAC-SHA256 → hex
func Crypto_HmacSha256(key: String, message: String) -> String {
let keylen: int = String_Len(key) as int;
let msglen: int = String_Len(message) as int;
let hmacBuf: *void = Alloc(32);
bux_hmac_sha256(key, keylen, message, msglen, hmacBuf);
let result: String = bux_bytes_to_hex(hmacBuf as *void, 32);
Free(hmacBuf);
return result;
}
// HMAC-SHA256 raw → base64
func Crypto_HmacSha256Raw(key: String, message: String) -> String {
let keylen: int = String_Len(key) as int;
let msglen: int = String_Len(message) as int;
let hmacBuf: *void = Alloc(32);
bux_hmac_sha256(key, keylen, message, msglen, hmacBuf);
let result: String = bux_base64_encode(hmacBuf as String, 32);
Free(hmacBuf);
return result;
}
// Random bytes → base64
func Crypto_RandomBytes(n: int) -> String {
if n <= 0 { return ""; }
let buf: *void = Alloc(n as uint);
if bux_random_bytes(buf, n) != 1 {
Free(buf);
return "";
}
let result: String = bux_base64_encode(buf as String, n);
Free(buf);
return result;
}
// Base64 decode
func Crypto_Base64Decode(s: String) -> String {
let outlen: int = 0;
return bux_base64_decode(s, String_Len(s) as int, &outlen);
}
// Base64 encode
func Crypto_Base64Encode(s: String) -> String {
return bux_base64_encode(s, String_Len(s) as int);
}
// HMAC-SHA256 raw → base64
func Crypto_HmacSha256Raw(key: String, message: String) -> String {
let keylen: int = String_Len(key) as int;
let msglen: int = String_Len(message) as int;
let hmacBuf: *void = Alloc(32);
bux_hmac_sha256(key, keylen, message, msglen, hmacBuf);
let result: String = bux_base64_encode(hmacBuf as String, 32);
Free(hmacBuf);
return result;
}
// Base64 decode
func Crypto_Base64Decode(s: String) -> String {
let outlen: int = 0;
return bux_base64_decode(s, String_Len(s) as int, &outlen);
}
}
+74 -74
View File
@@ -8,93 +8,93 @@
module Std::Fmt {
import Std::String::{
String_Eq,
String_FromInt,
String_FromFloat,
String_FromBool,
StringBuilder,
StringBuilder_New,
StringBuilder_Append,
StringBuilder_Build,
String_Chars
};
import Std::String::{
String_Eq,
String_FromInt,
String_FromFloat,
String_FromBool,
StringBuilder,
StringBuilder_New,
StringBuilder_Append,
StringBuilder_Build,
String_Chars
};
extern func bux_strlen(s: String) -> uint;
extern func bux_str_to_int(s: String) -> int64;
extern func bux_alloc(size: uint) -> *void;
extern func bux_strlen(s: String) -> uint;
extern func bux_str_to_int(s: String) -> int64;
extern func bux_alloc(size: uint) -> *void;
// Core formatting engine: replace {0}..{9} in template with args
func Fmt_Format(tmpl: String, argStrs: *String, argCount: int) -> String {
let sb: StringBuilder = StringBuilder_New();
var i: uint = 0;
let tmplLen: uint = bux_strlen(tmpl);
while i < tmplLen {
// Check for {
let ch: String = String_Chars(tmpl, i);
if String_Eq(ch, "{") {
let digitIdx: uint = i + 1;
if digitIdx < tmplLen {
let digitCh: String = String_Chars(tmpl, digitIdx);
let d: int64 = bux_str_to_int(digitCh);
if d >= 0 && d < argCount as int64 {
// Consume {d}
i = i + 2; // skip past digit
// Check for closing }
if i < tmplLen {
let closeCh: String = String_Chars(tmpl, i);
if String_Eq(closeCh, "}") {
i = i + 1; // skip }
let argStr: String = argStrs[d as uint];
StringBuilder_Append(&sb, argStr);
continue;
// Core formatting engine: replace {0}..{9} in template with args
func Fmt_Format(tmpl: String, argStrs: *String, argCount: int) -> String {
let sb: StringBuilder = StringBuilder_New();
var i: uint = 0;
let tmplLen: uint = bux_strlen(tmpl);
while i < tmplLen {
// Check for {
let ch: String = String_Chars(tmpl, i);
if String_Eq(ch, "{") {
let digitIdx: uint = i + 1;
if digitIdx < tmplLen {
let digitCh: String = String_Chars(tmpl, digitIdx);
let d: int64 = bux_str_to_int(digitCh);
if d >= 0 && d < argCount as int64 {
// Consume {d}
i = i + 2; // skip past digit
// Check for closing }
if i < tmplLen {
let closeCh: String = String_Chars(tmpl, i);
if String_Eq(closeCh, "}") {
i = i + 1; // skip }
let argStr: String = argStrs[d as uint];
StringBuilder_Append(&sb, argStr);
continue;
}
}
}
}
}
// Normal character: append it
StringBuilder_Append(&sb, ch);
i = i + 1;
}
// Normal character: append it
StringBuilder_Append(&sb, ch);
i = i + 1;
return StringBuilder_Build(&sb);
}
return StringBuilder_Build(&sb);
}
// Convenience wrappers
func Fmt_Fmt1(tmpl: String, a1: String) -> String {
var args: *String = bux_alloc(sizeof(String)) as *String;
args[0] = a1;
return Fmt_Format(tmpl, args, 1);
}
// Convenience wrappers
func Fmt_Fmt1(tmpl: String, a1: String) -> String {
var args: *String = bux_alloc(sizeof(String)) as *String;
args[0] = a1;
return Fmt_Format(tmpl, args, 1);
}
func Fmt_FmtInt(tmpl: String, val: int64) -> String {
let s: String = String_FromInt(val);
return Fmt_Fmt1(tmpl, s);
}
func Fmt_FmtInt(tmpl: String, val: int64) -> String {
let s: String = String_FromInt(val);
return Fmt_Fmt1(tmpl, s);
}
func Fmt_FmtBool(tmpl: String, val: bool) -> String {
let s: String = String_FromBool(val);
return Fmt_Fmt1(tmpl, s);
}
func Fmt_FmtBool(tmpl: String, val: bool) -> String {
let s: String = String_FromBool(val);
return Fmt_Fmt1(tmpl, s);
}
func Fmt_FmtFloat(tmpl: String, val: float64) -> String {
let s: String = String_FromFloat(val);
return Fmt_Fmt1(tmpl, s);
}
func Fmt_FmtFloat(tmpl: String, val: float64) -> String {
let s: String = String_FromFloat(val);
return Fmt_Fmt1(tmpl, s);
}
func Fmt_Fmt2(tmpl: String, a1: String, a2: String) -> String {
var args: *String = bux_alloc(2 * sizeof(String)) as *String;
args[0] = a1;
args[1] = a2;
return Fmt_Format(tmpl, args, 2);
}
func Fmt_Fmt2(tmpl: String, a1: String, a2: String) -> String {
var args: *String = bux_alloc(2 * sizeof(String)) as *String;
args[0] = a1;
args[1] = a2;
return Fmt_Format(tmpl, args, 2);
}
func Fmt_Fmt3(tmpl: String, a1: String, a2: String, a3: String) -> String {
var args: *String = bux_alloc(3 * sizeof(String)) as *String;
args[0] = a1;
args[1] = a2;
args[2] = a3;
return Fmt_Format(tmpl, args, 3);
}
func Fmt_Fmt3(tmpl: String, a1: String, a2: String, a3: String) -> String {
var args: *String = bux_alloc(3 * sizeof(String)) as *String;
args[0] = a1;
args[1] = a2;
args[2] = a3;
return Fmt_Format(tmpl, args, 3);
}
}
+12 -12
View File
@@ -1,19 +1,19 @@
module Std::Fs {
extern func bux_dir_exists(path: String) -> int;
extern func bux_mkdir_if_needed(path: String) -> int;
extern func bux_list_dir(dir: String, ext: String, out_count: *int) -> *String;
extern func bux_dir_exists(path: String) -> int;
extern func bux_mkdir_if_needed(path: String) -> int;
extern func bux_list_dir(dir: String, ext: String, out_count: *int) -> *String;
func DirExists(path: String) -> bool {
return bux_dir_exists(path) != 0;
}
func DirExists(path: String) -> bool {
return bux_dir_exists(path) != 0;
}
func Mkdir(path: String) -> bool {
return bux_mkdir_if_needed(path) != 0;
}
func Mkdir(path: String) -> bool {
return bux_mkdir_if_needed(path) != 0;
}
func ListDir(dir: String, ext: String, count: *int) -> *String {
return bux_list_dir(dir, ext, count);
}
func ListDir(dir: String, ext: String, count: *int) -> *String {
return bux_list_dir(dir, ext, count);
}
}
+21 -21
View File
@@ -1,28 +1,28 @@
module Std::Io {
extern func PrintLine(s: String);
extern func Print(s: String);
extern func PrintInt(n: int);
extern func PrintInt64(n: int64);
extern func PrintFloat(f: float64);
extern func PrintBool(b: bool);
extern func ReadLine() -> String;
extern func bux_read_file(path: String) -> String;
extern func bux_write_file(path: String, content: String) -> int;
extern func bux_file_exists(path: String) -> int;
extern func PrintLine(s: String);
extern func Print(s: String);
extern func PrintInt(n: int);
extern func PrintInt64(n: int64);
extern func PrintFloat(f: float64);
extern func PrintBool(b: bool);
extern func ReadLine() -> String;
extern func bux_read_file(path: String) -> String;
extern func bux_write_file(path: String, content: String) -> int;
extern func bux_file_exists(path: String) -> int;
func ReadFile(path: String) -> String {
return bux_read_file(path);
}
func ReadFile(path: String) -> String {
return bux_read_file(path);
}
func WriteFile(path: String, content: String) -> bool {
let r: int = bux_write_file(path, content);
return r != 0;
}
func WriteFile(path: String, content: String) -> bool {
let r: int = bux_write_file(path, content);
return r != 0;
}
func FileExists(path: String) -> bool {
let r: int = bux_file_exists(path);
return r != 0;
}
func FileExists(path: String) -> bool {
let r: int = bux_file_exists(path);
return r != 0;
}
}
+201 -201
View File
@@ -1,233 +1,233 @@
module Std::Iter {
import Std::Array::*;
import Std::Array::*;
struct Iter<T> {
data: *T,
len: uint,
pos: uint,
}
/* Create an iterator from an Array */
func Array_Iter<T>(arr: *Array<T>) -> Iter<T> {
return Iter<T> { data: arr.data, len: arr.len, pos: 0 };
}
/* Check if there are more elements */
func Iter_HasNext<T>(it: *Iter<T>) -> bool {
return it.pos < it.len;
}
/* Get the next element and advance (undefined if HasNext is false) */
func Iter_Next<T>(it: *Iter<T>) -> T {
let val: T = it.data[it.pos];
it.pos = it.pos + 1;
return val;
}
/* Peek current element without advancing (undefined if HasNext is false) */
func Iter_Peek<T>(it: *Iter<T>) -> T {
return it.data[it.pos];
}
/* Reset iterator to the beginning */
func Iter_Reset<T>(it: *Iter<T>) {
it.pos = 0;
}
/* Current position */
func Iter_Pos<T>(it: *Iter<T>) -> uint {
return it.pos;
}
/* Remaining length */
func Iter_Len<T>(it: *Iter<T>) -> uint {
return it.len;
}
/* Count remaining elements */
func Iter_Count<T>(it: *Iter<T>) -> uint {
return it.len - it.pos;
}
/* Skip N elements */
func Iter_Skip<T>(it: *Iter<T>, n: uint) {
it.pos = it.pos + n;
if it.pos > it.len {
it.pos = it.len;
struct Iter<T> {
data: *T,
len: uint,
pos: uint,
}
}
/* Take first N elements (by limiting len) */
func Iter_Take<T>(it: *Iter<T>, n: uint) -> Iter<T> {
var endPos: uint = it.pos + n;
if endPos > it.len {
endPos = it.len;
/* Create an iterator from an Array */
func Array_Iter<T>(arr: *Array<T>) -> Iter<T> {
return Iter<T> { data: arr.data, len: arr.len, pos: 0 };
}
return Iter<T> { data: it.data, len: endPos, pos: it.pos };
}
/* True if any remaining element equals value */
func Iter_AnyEq<T>(it: *Iter<T>, value: T) -> bool {
var i: uint = it.pos;
while i < it.len {
if it.data[i] == value {
return true;
/* Check if there are more elements */
func Iter_HasNext<T>(it: *Iter<T>) -> bool {
return it.pos < it.len;
}
/* Get the next element and advance (undefined if HasNext is false) */
func Iter_Next<T>(it: *Iter<T>) -> T {
let val: T = it.data[it.pos];
it.pos = it.pos + 1;
return val;
}
/* Peek current element without advancing (undefined if HasNext is false) */
func Iter_Peek<T>(it: *Iter<T>) -> T {
return it.data[it.pos];
}
/* Reset iterator to the beginning */
func Iter_Reset<T>(it: *Iter<T>) {
it.pos = 0;
}
/* Current position */
func Iter_Pos<T>(it: *Iter<T>) -> uint {
return it.pos;
}
/* Remaining length */
func Iter_Len<T>(it: *Iter<T>) -> uint {
return it.len;
}
/* Count remaining elements */
func Iter_Count<T>(it: *Iter<T>) -> uint {
return it.len - it.pos;
}
/* Skip N elements */
func Iter_Skip<T>(it: *Iter<T>, n: uint) {
it.pos = it.pos + n;
if it.pos > it.len {
it.pos = it.len;
}
i = i + 1;
}
return false;
}
/* True if every remaining element equals value (true if empty) */
func Iter_AllEq<T>(it: *Iter<T>, value: T) -> bool {
var i: uint = it.pos;
while i < it.len {
if it.data[i] != value {
return false;
/* Take first N elements (by limiting len) */
func Iter_Take<T>(it: *Iter<T>, n: uint) -> Iter<T> {
var endPos: uint = it.pos + n;
if endPos > it.len {
endPos = it.len;
}
i = i + 1;
return Iter<T> { data: it.data, len: endPos, pos: it.pos };
}
return true;
}
/* Collect remaining elements into a new Array */
func Iter_Collect<T>(it: *Iter<T>) -> Array<T> {
let remaining: uint = it.len - it.pos;
var cap: uint = remaining;
if cap == 0 {
cap = 1;
}
var arr: Array<T> = Array_New<T>(cap);
var i: uint = it.pos;
while i < it.len {
Array_Push<T>(&arr, it.data[i]);
i = i + 1;
}
return arr;
}
// ---------------------------------------------------------------------------
// Higher-order helpers (generic; fat func pointers / closures)
// ---------------------------------------------------------------------------
/* Map each remaining element through f: T → U, collect into Array<U> */
func Iter_Map<T, U>(it: *Iter<T>, f: func(T) -> U) -> Array<U> {
let remaining: uint = it.len - it.pos;
var cap: uint = remaining;
if cap == 0 {
cap = 1;
}
var out: Array<U> = Array_New<U>(cap);
var i: uint = it.pos;
while i < it.len {
let mapped: U = f(it.data[i]);
Array_Push<U>(&out, mapped);
i = i + 1;
}
return out;
}
/* Keep remaining elements for which pred returns true */
func Iter_Filter<T>(it: *Iter<T>, pred: func(T) -> bool) -> Array<T> {
let remaining: uint = it.len - it.pos;
var cap: uint = remaining;
if cap == 0 {
cap = 1;
}
var out: Array<T> = Array_New<T>(cap);
var i: uint = it.pos;
while i < it.len {
let v: T = it.data[i];
if pred(v) {
Array_Push<T>(&out, v);
/* True if any remaining element equals value */
func Iter_AnyEq<T>(it: *Iter<T>, value: T) -> bool {
var i: uint = it.pos;
while i < it.len {
if it.data[i] == value {
return true;
}
i = i + 1;
}
i = i + 1;
return false;
}
return out;
}
/* Left-fold: f(f(...f(init, x0), x1), ...) */
func Iter_Fold<T, Acc>(it: *Iter<T>, init: Acc, f: func(Acc, T) -> Acc) -> Acc {
var acc: Acc = init;
var i: uint = it.pos;
while i < it.len {
acc = f(acc, it.data[i]);
i = i + 1;
}
return acc;
}
/* Call f for each remaining element (return value of f is ignored) */
func Iter_ForEach<T>(it: *Iter<T>, f: func(T) -> int) {
var i: uint = it.pos;
while i < it.len {
let _ignored: int = f(it.data[i]);
i = i + 1;
}
}
/* True if any remaining element satisfies pred */
func Iter_Any<T>(it: *Iter<T>, pred: func(T) -> bool) -> bool {
var i: uint = it.pos;
while i < it.len {
if pred(it.data[i]) {
return true;
/* True if every remaining element equals value (true if empty) */
func Iter_AllEq<T>(it: *Iter<T>, value: T) -> bool {
var i: uint = it.pos;
while i < it.len {
if it.data[i] != value {
return false;
}
i = i + 1;
}
i = i + 1;
return true;
}
return false;
}
/* True if all remaining elements satisfy pred (true if empty) */
func Iter_All<T>(it: *Iter<T>, pred: func(T) -> bool) -> bool {
var i: uint = it.pos;
while i < it.len {
if !pred(it.data[i]) {
return false;
/* Collect remaining elements into a new Array */
func Iter_Collect<T>(it: *Iter<T>) -> Array<T> {
let remaining: uint = it.len - it.pos;
var cap: uint = remaining;
if cap == 0 {
cap = 1;
}
i = i + 1;
var arr: Array<T> = Array_New<T>(cap);
var i: uint = it.pos;
while i < it.len {
Array_Push<T>(&arr, it.data[i]);
i = i + 1;
}
return arr;
}
return true;
}
/* Sum remaining ints (specialized fold) */
func Iter_SumInt(it: *Iter<int>) -> int {
var total: int = 0;
var i: uint = it.pos;
while i < it.len {
total = total + it.data[i];
i = i + 1;
// ---------------------------------------------------------------------------
// Higher-order helpers (generic; fat func pointers / closures)
// ---------------------------------------------------------------------------
/* Map each remaining element through f: T → U, collect into Array<U> */
func Iter_Map<T, U>(it: *Iter<T>, f: func(T) -> U) -> Array<U> {
let remaining: uint = it.len - it.pos;
var cap: uint = remaining;
if cap == 0 {
cap = 1;
}
var out: Array<U> = Array_New<U>(cap);
var i: uint = it.pos;
while i < it.len {
let mapped: U = f(it.data[i]);
Array_Push<U>(&out, mapped);
i = i + 1;
}
return out;
}
return total;
}
// ---------------------------------------------------------------------------
// Int-specialized aliases (backward compatible with earlier examples)
// ---------------------------------------------------------------------------
/* Keep remaining elements for which pred returns true */
func Iter_Filter<T>(it: *Iter<T>, pred: func(T) -> bool) -> Array<T> {
let remaining: uint = it.len - it.pos;
var cap: uint = remaining;
if cap == 0 {
cap = 1;
}
var out: Array<T> = Array_New<T>(cap);
var i: uint = it.pos;
while i < it.len {
let v: T = it.data[i];
if pred(v) {
Array_Push<T>(&out, v);
}
i = i + 1;
}
return out;
}
func Iter_MapInt(it: *Iter<int>, f: func(int) -> int) -> Array<int> {
return Iter_Map<int, int>(it, f);
}
/* Left-fold: f(f(...f(init, x0), x1), ...) */
func Iter_Fold<T, Acc>(it: *Iter<T>, init: Acc, f: func(Acc, T) -> Acc) -> Acc {
var acc: Acc = init;
var i: uint = it.pos;
while i < it.len {
acc = f(acc, it.data[i]);
i = i + 1;
}
return acc;
}
func Iter_FilterInt(it: *Iter<int>, pred: func(int) -> bool) -> Array<int> {
return Iter_Filter<int>(it, pred);
}
/* Call f for each remaining element (return value of f is ignored) */
func Iter_ForEach<T>(it: *Iter<T>, f: func(T) -> int) {
var i: uint = it.pos;
while i < it.len {
let _ignored: int = f(it.data[i]);
i = i + 1;
}
}
func Iter_FoldInt(it: *Iter<int>, init: int, f: func(int, int) -> int) -> int {
return Iter_Fold<int, int>(it, init, f);
}
/* True if any remaining element satisfies pred */
func Iter_Any<T>(it: *Iter<T>, pred: func(T) -> bool) -> bool {
var i: uint = it.pos;
while i < it.len {
if pred(it.data[i]) {
return true;
}
i = i + 1;
}
return false;
}
func Iter_ForEachInt(it: *Iter<int>, f: func(int) -> int) {
Iter_ForEach<int>(it, f);
}
/* True if all remaining elements satisfy pred (true if empty) */
func Iter_All<T>(it: *Iter<T>, pred: func(T) -> bool) -> bool {
var i: uint = it.pos;
while i < it.len {
if !pred(it.data[i]) {
return false;
}
i = i + 1;
}
return true;
}
func Iter_AnyInt(it: *Iter<int>, pred: func(int) -> bool) -> bool {
return Iter_Any<int>(it, pred);
}
/* Sum remaining ints (specialized fold) */
func Iter_SumInt(it: *Iter<int>) -> int {
var total: int = 0;
var i: uint = it.pos;
while i < it.len {
total = total + it.data[i];
i = i + 1;
}
return total;
}
func Iter_AllInt(it: *Iter<int>, pred: func(int) -> bool) -> bool {
return Iter_All<int>(it, pred);
}
// ---------------------------------------------------------------------------
// Int-specialized aliases (backward compatible with earlier examples)
// ---------------------------------------------------------------------------
func Iter_MapInt(it: *Iter<int>, f: func(int) -> int) -> Array<int> {
return Iter_Map<int, int>(it, f);
}
func Iter_FilterInt(it: *Iter<int>, pred: func(int) -> bool) -> Array<int> {
return Iter_Filter<int>(it, pred);
}
func Iter_FoldInt(it: *Iter<int>, init: int, f: func(int, int) -> int) -> int {
return Iter_Fold<int, int>(it, init, f);
}
func Iter_ForEachInt(it: *Iter<int>, f: func(int) -> int) {
Iter_ForEach<int>(it, f);
}
func Iter_AnyInt(it: *Iter<int>, pred: func(int) -> bool) -> bool {
return Iter_Any<int>(it, pred);
}
func Iter_AllInt(it: *Iter<int>, pred: func(int) -> bool) -> bool {
return Iter_All<int>(it, pred);
}
}
+408 -408
View File
@@ -1,297 +1,287 @@
module Std::Json {
import Std::Mem::{Alloc, Realloc, Free};
import Std::String;
import Std::Mem::{Alloc, Realloc, Free};
import Std::String;
/* === Tags === */
const JsonTagNull: int = 0;
const JsonTagBool: int = 1;
const JsonTagNumber: int = 2;
const JsonTagString: int = 3;
const JsonTagArray: int = 4;
const JsonTagObject: int = 5;
/* === Tags === */
const JsonTagNull: int = 0;
const JsonTagBool: int = 1;
const JsonTagNumber: int = 2;
const JsonTagString: int = 3;
const JsonTagArray: int = 4;
const JsonTagObject: int = 5;
/* === Core type === */
struct JsonValue {
tag: int,
boolVal: bool,
numVal: float64,
strVal: String,
arrData: *JsonValue,
arrLen: uint,
arrCap: uint,
objKeys: *String,
objValues: *JsonValue,
objLen: uint,
objCap: uint
}
/* === Core type === */
struct JsonValue {
tag: int,
boolVal: bool,
numVal: float64,
strVal: String,
arrData: *JsonValue,
arrLen: uint,
arrCap: uint,
objKeys: *String,
objValues: *JsonValue,
objLen: uint,
objCap: uint
}
/* === Constructors === */
func Json_Null() -> JsonValue {
return JsonValue {
tag: JsonTagNull, boolVal: false, numVal: 0.0, strVal: "",
arrData: null, arrLen: 0, arrCap: 0,
objKeys: null, objValues: null, objLen: 0, objCap: 0
};
}
/* === Constructors === */
func Json_Null() -> JsonValue {
return JsonValue {
tag: JsonTagNull, boolVal: false, numVal: 0.0, strVal: "",
arrData: null, arrLen: 0, arrCap: 0,
objKeys: null, objValues: null, objLen: 0, objCap: 0
};
}
func Json_Bool(b: bool) -> JsonValue {
return JsonValue {
tag: JsonTagBool, boolVal: b, numVal: 0.0, strVal: "",
arrData: null, arrLen: 0, arrCap: 0,
objKeys: null, objValues: null, objLen: 0, objCap: 0
};
}
func Json_Bool(b: bool) -> JsonValue {
return JsonValue {
tag: JsonTagBool, boolVal: b, numVal: 0.0, strVal: "",
arrData: null, arrLen: 0, arrCap: 0,
objKeys: null, objValues: null, objLen: 0, objCap: 0
};
}
func Json_Number(n: float64) -> JsonValue {
return JsonValue {
tag: JsonTagNumber, boolVal: false, numVal: n, strVal: "",
arrData: null, arrLen: 0, arrCap: 0,
objKeys: null, objValues: null, objLen: 0, objCap: 0
};
}
func Json_Number(n: float64) -> JsonValue {
return JsonValue {
tag: JsonTagNumber, boolVal: false, numVal: n, strVal: "",
arrData: null, arrLen: 0, arrCap: 0,
objKeys: null, objValues: null, objLen: 0, objCap: 0
};
}
func Json_String(s: String) -> JsonValue {
return JsonValue {
tag: JsonTagString, boolVal: false, numVal: 0.0, strVal: s,
arrData: null, arrLen: 0, arrCap: 0,
objKeys: null, objValues: null, objLen: 0, objCap: 0
};
}
func Json_String(s: String) -> JsonValue {
return JsonValue {
tag: JsonTagString, boolVal: false, numVal: 0.0, strVal: s,
arrData: null, arrLen: 0, arrCap: 0,
objKeys: null, objValues: null, objLen: 0, objCap: 0
};
}
func Json_Array() -> JsonValue {
return JsonValue {
tag: JsonTagArray, boolVal: false, numVal: 0.0, strVal: "",
arrData: null, arrLen: 0, arrCap: 0,
objKeys: null, objValues: null, objLen: 0, objCap: 0
};
}
func Json_Array() -> JsonValue {
return JsonValue {
tag: JsonTagArray, boolVal: false, numVal: 0.0, strVal: "",
arrData: null, arrLen: 0, arrCap: 0,
objKeys: null, objValues: null, objLen: 0, objCap: 0
};
}
func Json_Object() -> JsonValue {
return JsonValue {
tag: JsonTagObject, boolVal: false, numVal: 0.0, strVal: "",
arrData: null, arrLen: 0, arrCap: 0,
objKeys: null, objValues: null, objLen: 0, objCap: 0
};
}
func Json_Object() -> JsonValue {
return JsonValue {
tag: JsonTagObject, boolVal: false, numVal: 0.0, strVal: "",
arrData: null, arrLen: 0, arrCap: 0,
objKeys: null, objValues: null, objLen: 0, objCap: 0
};
}
/* === Array helpers === */
func Json_ArrayLen(v: JsonValue) -> uint {
if v.tag != JsonTagArray { return 0; }
return v.arrLen;
}
/* === Array helpers === */
func Json_ArrayLen(v: JsonValue) -> uint {
if v.tag != JsonTagArray { return 0; }
return v.arrLen;
}
func Json_ArrayGet(v: JsonValue, index: uint) -> JsonValue {
if v.tag != JsonTagArray { return Json_Null(); }
if index >= v.arrLen { return Json_Null(); }
return v.arrData[index];
}
func Json_ArrayGet(v: JsonValue, index: uint) -> JsonValue {
if v.tag != JsonTagArray { return Json_Null(); }
if index >= v.arrLen { return Json_Null(); }
return v.arrData[index];
}
func Json_ArrayPush(self: *JsonValue, val: JsonValue) {
if self.tag != JsonTagArray { return; }
if self.arrLen >= self.arrCap {
let arrNewCap: uint = self.arrCap;
if arrNewCap == 0 {
self.arrCap = 4;
self.arrData = Alloc(4 * sizeof(JsonValue)) as *JsonValue;
} else {
let doubleCap: uint = arrNewCap * 2;
self.arrCap = doubleCap;
self.arrData = Realloc(self.arrData as *void, doubleCap * sizeof(JsonValue)) as *JsonValue;
func Json_ArrayPush(self: *JsonValue, val: JsonValue) {
if self.tag != JsonTagArray { return; }
if self.arrLen >= self.arrCap {
let arrNewCap: uint = self.arrCap;
if arrNewCap == 0 {
self.arrCap = 4;
self.arrData = Alloc(4 * sizeof(JsonValue)) as *JsonValue;
} else {
let doubleCap: uint = arrNewCap * 2;
self.arrCap = doubleCap;
self.arrData = Realloc(self.arrData as *void, doubleCap * sizeof(JsonValue)) as *JsonValue;
}
}
self.arrData[self.arrLen] = val;
self.arrLen = self.arrLen + 1;
}
self.arrData[self.arrLen] = val;
self.arrLen = self.arrLen + 1;
}
/* === Object helpers === */
func Json_ObjectLen(v: JsonValue) -> uint {
if v.tag != JsonTagObject { return 0; }
return v.objLen;
}
/* === Object helpers === */
func Json_ObjectLen(v: JsonValue) -> uint {
if v.tag != JsonTagObject { return 0; }
return v.objLen;
}
func Json_ObjectGet(v: JsonValue, key: String) -> JsonValue {
if v.tag != JsonTagObject { return Json_Null(); }
var i: uint = 0;
while i < v.objLen {
if String_Eq(v.objKeys[i], key) {
return v.objValues[i];
func Json_ObjectGet(v: JsonValue, key: String) -> JsonValue {
if v.tag != JsonTagObject { return Json_Null(); }
var i: uint = 0;
while i < v.objLen {
if String_Eq(v.objKeys[i], key) {
return v.objValues[i];
}
i = i + 1;
}
i = i + 1;
return Json_Null();
}
return Json_Null();
}
func Json_ObjectHas(v: JsonValue, key: String) -> bool {
if v.tag != JsonTagObject { return false; }
var i: uint = 0;
while i < v.objLen {
if String_Eq(v.objKeys[i], key) {
return true;
func Json_ObjectHas(v: JsonValue, key: String) -> bool {
if v.tag != JsonTagObject { return false; }
var i: uint = 0;
while i < v.objLen {
if String_Eq(v.objKeys[i], key) {
return true;
}
i = i + 1;
}
i = i + 1;
return false;
}
return false;
}
func Json_ObjectSet(self: *JsonValue, key: String, val: JsonValue) {
if self.tag != JsonTagObject { return; }
var i: uint = 0;
while i < self.objLen {
if String_Eq(self.objKeys[i], key) {
self.objValues[i] = val;
return;
func Json_ObjectSet(self: *JsonValue, key: String, val: JsonValue) {
if self.tag != JsonTagObject { return; }
var i: uint = 0;
while i < self.objLen {
if String_Eq(self.objKeys[i], key) {
self.objValues[i] = val;
return;
}
i = i + 1;
}
i = i + 1;
}
if self.objLen >= self.objCap {
let objNewCap: uint = self.objCap;
if objNewCap == 0 {
self.objCap = 4;
self.objKeys = Alloc(4 * sizeof(String)) as *String;
self.objValues = Alloc(4 * sizeof(JsonValue)) as *JsonValue;
} else {
let doubleCap: uint = objNewCap * 2;
self.objCap = doubleCap;
self.objKeys = Realloc(self.objKeys as *void, doubleCap * sizeof(String)) as *String;
self.objValues = Realloc(self.objValues as *void, doubleCap * sizeof(JsonValue)) as *JsonValue;
if self.objLen >= self.objCap {
let objNewCap: uint = self.objCap;
if objNewCap == 0 {
self.objCap = 4;
self.objKeys = Alloc(4 * sizeof(String)) as *String;
self.objValues = Alloc(4 * sizeof(JsonValue)) as *JsonValue;
} else {
let doubleCap: uint = objNewCap * 2;
self.objCap = doubleCap;
self.objKeys = Realloc(self.objKeys as *void, doubleCap * sizeof(String)) as *String;
self.objValues = Realloc(self.objValues as *void, doubleCap * sizeof(JsonValue)) as *JsonValue;
}
}
self.objKeys[self.objLen] = key;
self.objValues[self.objLen] = val;
self.objLen = self.objLen + 1;
}
self.objKeys[self.objLen] = key;
self.objValues[self.objLen] = val;
self.objLen = self.objLen + 1;
}
/* === Accessors === */
func Json_IsNull(v: JsonValue) -> bool {
return v.tag == JsonTagNull;
}
func Json_AsBool(v: JsonValue) -> bool {
if v.tag == JsonTagBool { return v.boolVal; }
return false;
}
func Json_AsNumber(v: JsonValue) -> float64 {
if v.tag == JsonTagNumber { return v.numVal; }
return 0.0;
}
func Json_AsString(v: JsonValue) -> String {
if v.tag == JsonTagString { return v.strVal; }
return "";
}
/* === Parser === */
struct JsonParser {
src: String,
pos: uint,
len: uint,
error: String
}
func JsonParser_Peek(p: *JsonParser) -> int {
if p.pos >= p.len { return 0; }
return p.src[p.pos] as int;
}
func JsonParser_Advance(p: *JsonParser) {
if p.pos < p.len {
p.pos = p.pos + 1;
/* === Accessors === */
func Json_IsNull(v: JsonValue) -> bool {
return v.tag == JsonTagNull;
}
}
func JsonParser_SkipWhitespace(p: *JsonParser) {
while true {
let c: int = JsonParser_Peek(p);
if c == 32 || c == 9 || c == 10 || c == 13 {
JsonParser_Advance(p);
} else {
return;
}
func Json_AsBool(v: JsonValue) -> bool {
if v.tag == JsonTagBool { return v.boolVal; }
return false;
}
}
func JsonParser_Match(p: *JsonParser, expected: String) -> bool {
let elen: uint = String_Len(expected);
if p.pos + elen > p.len { return false; }
var i: uint = 0;
while i < elen {
if p.src[p.pos + i] != expected[i] {
return false;
}
i = i + 1;
func Json_AsNumber(v: JsonValue) -> float64 {
if v.tag == JsonTagNumber { return v.numVal; }
return 0.0;
}
p.pos = p.pos + elen;
return true;
}
func JsonParser_ParseValue(p: *JsonParser) -> JsonValue;
func JsonParser_ParseString(p: *JsonParser) -> String {
if JsonParser_Peek(p) != 34 {
p.error = "Expected string";
func Json_AsString(v: JsonValue) -> String {
if v.tag == JsonTagString { return v.strVal; }
return "";
}
JsonParser_Advance(p);
let sb: StringBuilder = StringBuilder_New();
while true {
let c: int = JsonParser_Peek(p);
if c == 0 || c == 34 {
break;
}
if c == 92 {
JsonParser_Advance(p);
let esc: int = JsonParser_Peek(p);
if esc == 0 {
p.error = "Unterminated string escape";
StringBuilder_Free(&sb);
return "";
}
if esc == 110 { StringBuilder_AppendChar(&sb, 10 as char8); } // \n
else if esc == 116 { StringBuilder_AppendChar(&sb, 9 as char8); } // \t
else if esc == 114 { StringBuilder_AppendChar(&sb, 13 as char8); } // \r
else if esc == 98 { StringBuilder_AppendChar(&sb, 8 as char8); } // \b
else if esc == 102 { StringBuilder_AppendChar(&sb, 12 as char8); } // \f
else if esc == 34 { StringBuilder_AppendChar(&sb, 34 as char8); } // \"
else if esc == 92 { StringBuilder_AppendChar(&sb, 92 as char8); } // \\
else {
// Unknown escape — keep literal
StringBuilder_AppendChar(&sb, 92 as char8);
StringBuilder_AppendChar(&sb, esc as char8);
}
JsonParser_Advance(p);
} else {
StringBuilder_AppendChar(&sb, c as char8);
JsonParser_Advance(p);
/* === Parser === */
struct JsonParser {
src: String,
pos: uint,
len: uint,
error: String
}
func JsonParser_Peek(p: *JsonParser) -> int {
if p.pos >= p.len { return 0; }
return p.src[p.pos] as int;
}
func JsonParser_Advance(p: *JsonParser) {
if p.pos < p.len {
p.pos = p.pos + 1;
}
}
if JsonParser_Peek(p) != 34 {
p.error = "Unterminated string";
func JsonParser_SkipWhitespace(p: *JsonParser) {
while true {
let c: int = JsonParser_Peek(p);
if c == 32 || c == 9 || c == 10 || c == 13 {
JsonParser_Advance(p);
} else {
return;
}
}
}
func JsonParser_Match(p: *JsonParser, expected: String) -> bool {
let elen: uint = String_Len(expected);
if p.pos + elen > p.len { return false; }
var i: uint = 0;
while i < elen {
if p.src[p.pos + i] != expected[i] {
return false;
}
i = i + 1;
}
p.pos = p.pos + elen;
return true;
}
func JsonParser_ParseValue(p: *JsonParser) -> JsonValue;
func JsonParser_ParseString(p: *JsonParser) -> String {
if JsonParser_Peek(p) != 34 {
p.error = "Expected string";
return "";
}
JsonParser_Advance(p);
let sb: StringBuilder = StringBuilder_New();
while true {
let c: int = JsonParser_Peek(p);
if c == 0 || c == 34 {
break;
}
if c == 92 {
JsonParser_Advance(p);
let esc: int = JsonParser_Peek(p);
if esc == 0 {
p.error = "Unterminated string escape";
StringBuilder_Free(&sb);
return "";
}
if esc == 110 { StringBuilder_AppendChar(&sb, 10 as char8); } // \n
else if esc == 116 { StringBuilder_AppendChar(&sb, 9 as char8); } // \t
else if esc == 114 { StringBuilder_AppendChar(&sb, 13 as char8); } // \r
else if esc == 98 { StringBuilder_AppendChar(&sb, 8 as char8); } // \b
else if esc == 102 { StringBuilder_AppendChar(&sb, 12 as char8); } // \f
else if esc == 34 { StringBuilder_AppendChar(&sb, 34 as char8); } // \"
else if esc == 92 { StringBuilder_AppendChar(&sb, 92 as char8); } // \\
else {
// Unknown escape — keep literal
StringBuilder_AppendChar(&sb, 92 as char8);
StringBuilder_AppendChar(&sb, esc as char8);
}
JsonParser_Advance(p);
} else {
StringBuilder_AppendChar(&sb, c as char8);
JsonParser_Advance(p);
}
}
if JsonParser_Peek(p) != 34 {
p.error = "Unterminated string";
StringBuilder_Free(&sb);
return "";
}
JsonParser_Advance(p);
let result: String = StringBuilder_Build(&sb);
StringBuilder_Free(&sb);
return "";
return result;
}
JsonParser_Advance(p);
let result: String = StringBuilder_Build(&sb);
StringBuilder_Free(&sb);
return result;
}
func JsonParser_ParseNumber(p: *JsonParser) -> JsonValue {
let start: uint = p.pos;
let c0: int = JsonParser_Peek(p);
if c0 == 45 {
JsonParser_Advance(p);
}
while true {
let c: int = JsonParser_Peek(p);
if c >= 48 && c <= 57 {
func JsonParser_ParseNumber(p: *JsonParser) -> JsonValue {
let start: uint = p.pos;
let c0: int = JsonParser_Peek(p);
if c0 == 45 {
JsonParser_Advance(p);
} else {
break;
}
}
if JsonParser_Peek(p) == 46 {
JsonParser_Advance(p);
while true {
let c: int = JsonParser_Peek(p);
if c >= 48 && c <= 57 {
@@ -300,193 +290,203 @@ func JsonParser_ParseNumber(p: *JsonParser) -> JsonValue {
break;
}
}
if JsonParser_Peek(p) == 46 {
JsonParser_Advance(p);
while true {
let c: int = JsonParser_Peek(p);
if c >= 48 && c <= 57 {
JsonParser_Advance(p);
} else {
break;
}
}
}
let numStr: String = String_Slice(p.src, start, p.pos - start);
let n: float64 = String_ToFloat(numStr);
return Json_Number(n);
}
let numStr: String = String_Slice(p.src, start, p.pos - start);
let n: float64 = String_ToFloat(numStr);
return Json_Number(n);
}
func JsonParser_ParseArray(p: *JsonParser) -> JsonValue {
JsonParser_Advance(p);
var arr: JsonValue = Json_Array();
JsonParser_SkipWhitespace(p);
if JsonParser_Peek(p) == 93 {
func JsonParser_ParseArray(p: *JsonParser) -> JsonValue {
JsonParser_Advance(p);
return arr;
}
while true {
var arr: JsonValue = Json_Array();
JsonParser_SkipWhitespace(p);
let val: JsonValue = JsonParser_ParseValue(p);
if p.error != "" { return Json_Null(); }
Json_ArrayPush(&arr, val);
JsonParser_SkipWhitespace(p);
let c: int = JsonParser_Peek(p);
if c == 93 {
if JsonParser_Peek(p) == 93 {
JsonParser_Advance(p);
return arr;
}
if c == 44 {
JsonParser_Advance(p);
} else {
p.error = "Expected ',' or ']' in array";
return Json_Null();
while true {
JsonParser_SkipWhitespace(p);
let val: JsonValue = JsonParser_ParseValue(p);
if p.error != "" { return Json_Null(); }
Json_ArrayPush(&arr, val);
JsonParser_SkipWhitespace(p);
let c: int = JsonParser_Peek(p);
if c == 93 {
JsonParser_Advance(p);
return arr;
}
if c == 44 {
JsonParser_Advance(p);
} else {
p.error = "Expected ',' or ']' in array";
return Json_Null();
}
}
}
}
func JsonParser_ParseObject(p: *JsonParser) -> JsonValue {
JsonParser_Advance(p);
var obj: JsonValue = Json_Object();
JsonParser_SkipWhitespace(p);
if JsonParser_Peek(p) == 125 {
func JsonParser_ParseObject(p: *JsonParser) -> JsonValue {
JsonParser_Advance(p);
return obj;
}
while true {
var obj: JsonValue = Json_Object();
JsonParser_SkipWhitespace(p);
let key: String = JsonParser_ParseString(p);
if p.error != "" { return Json_Null(); }
JsonParser_SkipWhitespace(p);
if JsonParser_Peek(p) != 58 {
p.error = "Expected ':' after object key";
return Json_Null();
}
JsonParser_Advance(p);
JsonParser_SkipWhitespace(p);
let val: JsonValue = JsonParser_ParseValue(p);
if p.error != "" { return Json_Null(); }
Json_ObjectSet(&obj, key, val);
JsonParser_SkipWhitespace(p);
let c: int = JsonParser_Peek(p);
if c == 125 {
if JsonParser_Peek(p) == 125 {
JsonParser_Advance(p);
return obj;
}
if c == 44 {
while true {
JsonParser_SkipWhitespace(p);
let key: String = JsonParser_ParseString(p);
if p.error != "" { return Json_Null(); }
JsonParser_SkipWhitespace(p);
if JsonParser_Peek(p) != 58 {
p.error = "Expected ':' after object key";
return Json_Null();
}
JsonParser_Advance(p);
} else {
p.error = "Expected ',' or '}' in object";
JsonParser_SkipWhitespace(p);
let val: JsonValue = JsonParser_ParseValue(p);
if p.error != "" { return Json_Null(); }
Json_ObjectSet(&obj, key, val);
JsonParser_SkipWhitespace(p);
let c: int = JsonParser_Peek(p);
if c == 125 {
JsonParser_Advance(p);
return obj;
}
if c == 44 {
JsonParser_Advance(p);
} else {
p.error = "Expected ',' or '}' in object";
return Json_Null();
}
}
}
func JsonParser_ParseValue(p: *JsonParser) -> JsonValue {
JsonParser_SkipWhitespace(p);
let c: int = JsonParser_Peek(p);
if c == 0 {
p.error = "Unexpected end of input";
return Json_Null();
}
}
}
func JsonParser_ParseValue(p: *JsonParser) -> JsonValue {
JsonParser_SkipWhitespace(p);
let c: int = JsonParser_Peek(p);
if c == 0 {
p.error = "Unexpected end of input";
return Json_Null();
}
if c == 34 {
return Json_String(JsonParser_ParseString(p));
}
if c == 123 {
return JsonParser_ParseObject(p);
}
if c == 91 {
return JsonParser_ParseArray(p);
}
if c == 116 {
if JsonParser_Match(p, "true") {
return Json_Bool(true);
if c == 34 {
return Json_String(JsonParser_ParseString(p));
}
p.error = "Expected 'true'";
return Json_Null();
}
if c == 102 {
if JsonParser_Match(p, "false") {
return Json_Bool(false);
if c == 123 {
return JsonParser_ParseObject(p);
}
p.error = "Expected 'false'";
return Json_Null();
}
if c == 110 {
if JsonParser_Match(p, "null") {
if c == 91 {
return JsonParser_ParseArray(p);
}
if c == 116 {
if JsonParser_Match(p, "true") {
return Json_Bool(true);
}
p.error = "Expected 'true'";
return Json_Null();
}
p.error = "Expected 'null'";
if c == 102 {
if JsonParser_Match(p, "false") {
return Json_Bool(false);
}
p.error = "Expected 'false'";
return Json_Null();
}
if c == 110 {
if JsonParser_Match(p, "null") {
return Json_Null();
}
p.error = "Expected 'null'";
return Json_Null();
}
if (c >= 48 && c <= 57) || c == 45 {
return JsonParser_ParseNumber(p);
}
p.error = "Unexpected character";
return Json_Null();
}
if (c >= 48 && c <= 57) || c == 45 {
return JsonParser_ParseNumber(p);
}
p.error = "Unexpected character";
return Json_Null();
}
/* === Public parser === */
func Json_Parse(s: String) -> JsonValue {
var p: JsonParser = JsonParser { src: s, pos: 0, len: String_Len(s), error: "" };
let result: JsonValue = JsonParser_ParseValue(&p);
JsonParser_SkipWhitespace(&p);
if p.error == "" && p.pos != p.len {
p.error = "Trailing data after JSON value";
return Json_Null();
}
return result;
}
/* === Serializer === */
func Json_StringifyImpl(sb: *StringBuilder, v: JsonValue) {
if v.tag == JsonTagNull {
StringBuilder_Append(sb, "null");
return;
}
if v.tag == JsonTagBool {
if v.boolVal {
StringBuilder_Append(sb, "true");
} else {
StringBuilder_Append(sb, "false");
/* === Public parser === */
func Json_Parse(s: String) -> JsonValue {
var p: JsonParser = JsonParser { src: s, pos: 0, len: String_Len(s), error: "" };
let result: JsonValue = JsonParser_ParseValue(&p);
JsonParser_SkipWhitespace(&p);
if p.error == "" && p.pos != p.len {
p.error = "Trailing data after JSON value";
return Json_Null();
}
return;
return result;
}
if v.tag == JsonTagNumber {
StringBuilder_AppendFloat(sb, v.numVal);
return;
}
if v.tag == JsonTagString {
StringBuilder_AppendChar(sb, 34 as char8);
StringBuilder_Append(sb, v.strVal);
StringBuilder_AppendChar(sb, 34 as char8);
return;
}
if v.tag == JsonTagArray {
StringBuilder_AppendChar(sb, 91 as char8);
var i: uint = 0;
while i < v.arrLen {
if i > 0 {
StringBuilder_AppendChar(sb, 44 as char8);
/* === Serializer === */
func Json_StringifyImpl(sb: *StringBuilder, v: JsonValue) {
if v.tag == JsonTagNull {
StringBuilder_Append(sb, "null");
return;
}
if v.tag == JsonTagBool {
if v.boolVal {
StringBuilder_Append(sb, "true");
} else {
StringBuilder_Append(sb, "false");
}
Json_StringifyImpl(sb, v.arrData[i]);
i = i + 1;
return;
}
StringBuilder_AppendChar(sb, 93 as char8);
return;
}
if v.tag == JsonTagObject {
StringBuilder_AppendChar(sb, 123 as char8);
var i: uint = 0;
while i < v.objLen {
if i > 0 {
StringBuilder_AppendChar(sb, 44 as char8);
if v.tag == JsonTagNumber {
StringBuilder_AppendFloat(sb, v.numVal);
return;
}
if v.tag == JsonTagString {
StringBuilder_AppendChar(sb, 34 as char8);
StringBuilder_Append(sb, v.strVal);
StringBuilder_AppendChar(sb, 34 as char8);
return;
}
if v.tag == JsonTagArray {
StringBuilder_AppendChar(sb, 91 as char8);
var i: uint = 0;
while i < v.arrLen {
if i > 0 {
StringBuilder_AppendChar(sb, 44 as char8);
}
Json_StringifyImpl(sb, v.arrData[i]);
i = i + 1;
}
StringBuilder_AppendChar(sb, 34 as char8);
StringBuilder_Append(sb, v.objKeys[i]);
StringBuilder_AppendChar(sb, 34 as char8);
StringBuilder_AppendChar(sb, 58 as char8);
Json_StringifyImpl(sb, v.objValues[i]);
i = i + 1;
StringBuilder_AppendChar(sb, 93 as char8);
return;
}
if v.tag == JsonTagObject {
StringBuilder_AppendChar(sb, 123 as char8);
var i: uint = 0;
while i < v.objLen {
if i > 0 {
StringBuilder_AppendChar(sb, 44 as char8);
}
StringBuilder_AppendChar(sb, 34 as char8);
StringBuilder_Append(sb, v.objKeys[i]);
StringBuilder_AppendChar(sb, 34 as char8);
StringBuilder_AppendChar(sb, 58 as char8);
Json_StringifyImpl(sb, v.objValues[i]);
i = i + 1;
}
StringBuilder_AppendChar(sb, 125 as char8);
return;
}
StringBuilder_AppendChar(sb, 125 as char8);
return;
}
}
func Json_Stringify(v: JsonValue) -> String {
let sb: StringBuilder = StringBuilder_New();
Json_StringifyImpl(&sb, v);
return StringBuilder_Build(&sb);
}
func Json_Stringify(v: JsonValue) -> String {
let sb: StringBuilder = StringBuilder_New();
Json_StringifyImpl(&sb, v);
return StringBuilder_Build(&sb);
}
}
+211 -203
View File
@@ -1,242 +1,250 @@
module Std::Map {
extern func bux_hash_bytes(ptr: *void, size: uint) -> uint;
extern func bux_hash_string(s: String) -> uint;
extern func bux_hash_bytes(ptr: *void, size: uint) -> uint;
extern func bux_hash_string(s: String) -> uint;
// ---------------------------------------------------------------------------
// Generic Map<K, V> — works with value-type keys (int, float, etc.)
// For String keys, use StringMap below.
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// Generic Map<K, V> — works with value-type keys (int, float, etc.)
// For String keys, use StringMap below.
// ---------------------------------------------------------------------------
struct MapEntry<K, V> {
key: K,
value: V,
occupied: bool,
}
struct Map<K, V> {
entries: *MapEntry<K, V>,
cap: uint,
len: uint,
}
func Map_New<K, V>(cap: uint) -> Map<K, V> {
let total: uint = cap * sizeof(MapEntry<K, V>);
let data: *MapEntry<K, V> = bux_alloc(total) as *MapEntry<K, V>;
var i: uint = 0;
while i < cap {
data[i].occupied = false;
i = i + 1;
struct MapEntry<K, V> {
key: K,
value: V,
occupied: bool,
}
return Map<K, V> { entries: data, cap: cap, len: 0 };
}
func Map_Set<K, V>(m: *Map<K, V>, key: K, value: V) {
var keyPtr: *K = &key;
let hash: uint = bux_hash_bytes(keyPtr as *void, sizeof(K));
var idx: uint = hash % m.cap;
while m.entries[idx].occupied {
if m.entries[idx].key == key {
m.entries[idx].value = value;
return;
struct Map<K, V> {
entries: *MapEntry<K, V>,
cap: uint,
len: uint,
}
func Map_New<K, V>(cap: uint) -> Map<K, V> {
let total: uint = cap * sizeof(MapEntry<K, V>);
let data: *MapEntry<K, V> = bux_alloc(total) as *MapEntry<K, V>;
var i: uint = 0;
while i < cap {
data[i].occupied = false;
i = i + 1;
}
idx = (idx + 1) % m.cap;
return Map<K, V> { entries: data, cap: cap, len: 0 };
}
m.entries[idx].key = key;
m.entries[idx].value = value;
m.entries[idx].occupied = true;
m.len = m.len + 1;
}
func Map_Get<K, V>(m: *Map<K, V>, key: K) -> V {
var keyPtr: *K = &key;
let hash: uint = bux_hash_bytes(keyPtr as *void, sizeof(K));
var idx: uint = hash % m.cap;
while m.entries[idx].occupied {
if m.entries[idx].key == key {
return m.entries[idx].value;
func Map_Set<K, V>(m: *Map<K, V>, key: K, value: V) {
var keyPtr: *K = &key;
let hash: uint = bux_hash_bytes(keyPtr as *void, sizeof(K));
var idx: uint = hash % m.cap;
while m.entries[idx].occupied {
if m.entries[idx].key == key {
m.entries[idx].value = value;
return;
}
idx = (idx + 1) % m.cap;
}
idx = (idx + 1) % m.cap;
m.entries[idx].key = key;
m.entries[idx].value = value;
m.entries[idx].occupied = true;
m.len = m.len + 1;
}
// Return zero value for missing key
var zero: V = 0 as V;
return zero;
}
func Map_Has<K, V>(m: *Map<K, V>, key: K) -> bool {
var keyPtr: *K = &key;
let hash: uint = bux_hash_bytes(keyPtr as *void, sizeof(K));
var idx: uint = hash % m.cap;
while m.entries[idx].occupied {
if m.entries[idx].key == key {
return true;
func Map_Get<K, V>(m: *Map<K, V>, key: K) -> V {
var keyPtr: *K = &key;
let hash: uint = bux_hash_bytes(keyPtr as *void, sizeof(K));
var idx: uint = hash % m.cap;
while m.entries[idx].occupied {
if m.entries[idx].key == key {
return m.entries[idx].value;
}
idx = (idx + 1) % m.cap;
}
idx = (idx + 1) % m.cap;
// Return zero value for missing key
var zero: V = 0 as V;
return zero;
}
return false;
}
func Map_Len<K, V>(m: *Map<K, V>) -> uint {
return m.len;
}
func Map_IsEmpty<K, V>(m: *Map<K, V>) -> bool {
return m.len == 0;
}
/* Remove key if present. Rebuilds the table to keep open-addressing correct. */
func Map_Remove<K, V>(m: *Map<K, V>, key: K) -> bool {
if !Map_Has<K, V>(m, key) {
func Map_Has<K, V>(m: *Map<K, V>, key: K) -> bool {
var keyPtr: *K = &key;
let hash: uint = bux_hash_bytes(keyPtr as *void, sizeof(K));
var idx: uint = hash % m.cap;
while m.entries[idx].occupied {
if m.entries[idx].key == key {
return true;
}
idx = (idx + 1) % m.cap;
}
return false;
}
var fresh: Map<K, V> = Map_New<K, V>(m.cap);
var i: uint = 0;
while i < m.cap {
if m.entries[i].occupied {
if m.entries[i].key != key {
Map_Set<K, V>(&fresh, m.entries[i].key, m.entries[i].value);
func Map_Len<K, V>(m: *Map<K, V>) -> uint {
return m.len;
}
func Map_IsEmpty<K, V>(m: *Map<K, V>) -> bool {
return m.len == 0;
}
/* Remove key if present. Rebuilds the table to keep open-addressing correct. */
func Map_Remove<K, V>(m: *Map<K, V>, key: K) -> bool {
if !Map_Has<K, V>(m, key) {
return false;
}
var fresh: Map<K, V> = Map_New<K, V>(m.cap);
var i: uint = 0;
while i < m.cap {
if m.entries[i].occupied {
if m.entries[i].key != key {
Map_Set<K, V>(&fresh, m.entries[i].key, m.entries[i].value);
}
}
i = i + 1;
}
i = i + 1;
bux_free(m.entries as *void);
m.entries = fresh.entries;
m.cap = fresh.cap;
m.len = fresh.len;
// Ownership transferred to `m` — clear `fresh` so auto-Drop does not free twice
fresh.entries = null as *MapEntry<K, V>;
fresh.cap = 0;
fresh.len = 0;
return true;
}
bux_free(m.entries as *void);
m.entries = fresh.entries;
m.cap = fresh.cap;
m.len = fresh.len;
return true;
}
func Map_Clear<K, V>(m: *Map<K, V>) {
var i: uint = 0;
while i < m.cap {
m.entries[i].occupied = false;
i = i + 1;
}
m.len = 0;
}
func Map_Free<K, V>(m: *Map<K, V>) {
bux_free(m.entries as *void);
m.entries = null as *MapEntry<K, V>;
m.cap = 0;
m.len = 0;
}
func Map_Drop<K, V>(m: *Map<K, V>) {
Map_Free<K, V>(m);
}
// ---------------------------------------------------------------------------
// StringMap<V> — specialized Map for String keys, using strcmp
// ---------------------------------------------------------------------------
struct StringMapEntry<V> {
key: String,
value: V,
occupied: bool,
}
struct StringMap<V> {
entries: *StringMapEntry<V>,
cap: uint,
len: uint,
}
func StringMap_New<V>(cap: uint) -> StringMap<V> {
let total: uint = cap * sizeof(StringMapEntry<V>);
let data: *StringMapEntry<V> = bux_alloc(total) as *StringMapEntry<V>;
var i: uint = 0;
while i < cap {
data[i].occupied = false;
i = i + 1;
}
return StringMap<V> { entries: data, cap: cap, len: 0 };
}
func StringMap_Set<V>(m: *StringMap<V>, key: String, value: V) {
let hash: uint = bux_hash_string(key);
var idx: uint = hash % m.cap;
while m.entries[idx].occupied {
if String_Eq(m.entries[idx].key, key) {
m.entries[idx].value = value;
return;
func Map_Clear<K, V>(m: *Map<K, V>) {
var i: uint = 0;
while i < m.cap {
m.entries[i].occupied = false;
i = i + 1;
}
idx = (idx + 1) % m.cap;
m.len = 0;
}
m.entries[idx].key = key;
m.entries[idx].value = value;
m.entries[idx].occupied = true;
m.len = m.len + 1;
}
func StringMap_Get<V>(m: *StringMap<V>, key: String) -> V {
let hash: uint = bux_hash_string(key);
var idx: uint = hash % m.cap;
while m.entries[idx].occupied {
if String_Eq(m.entries[idx].key, key) {
return m.entries[idx].value;
func Map_Free<K, V>(m: *Map<K, V>) {
bux_free(m.entries as *void);
m.entries = null as *MapEntry<K, V>;
m.cap = 0;
m.len = 0;
}
func Map_Drop<K, V>(m: *Map<K, V>) {
Map_Free<K, V>(m);
}
// ---------------------------------------------------------------------------
// StringMap<V> — specialized Map for String keys, using strcmp
// ---------------------------------------------------------------------------
struct StringMapEntry<V> {
key: String,
value: V,
occupied: bool,
}
struct StringMap<V> {
entries: *StringMapEntry<V>,
cap: uint,
len: uint,
}
func StringMap_New<V>(cap: uint) -> StringMap<V> {
let total: uint = cap * sizeof(StringMapEntry<V>);
let data: *StringMapEntry<V> = bux_alloc(total) as *StringMapEntry<V>;
var i: uint = 0;
while i < cap {
data[i].occupied = false;
i = i + 1;
}
idx = (idx + 1) % m.cap;
return StringMap<V> { entries: data, cap: cap, len: 0 };
}
var zero: V = 0 as V;
return zero;
}
func StringMap_Has<V>(m: *StringMap<V>, key: String) -> bool {
let hash: uint = bux_hash_string(key);
var idx: uint = hash % m.cap;
while m.entries[idx].occupied {
if String_Eq(m.entries[idx].key, key) {
return true;
func StringMap_Set<V>(m: *StringMap<V>, key: String, value: V) {
let hash: uint = bux_hash_string(key);
var idx: uint = hash % m.cap;
while m.entries[idx].occupied {
if String_Eq(m.entries[idx].key, key) {
m.entries[idx].value = value;
return;
}
idx = (idx + 1) % m.cap;
}
idx = (idx + 1) % m.cap;
m.entries[idx].key = key;
m.entries[idx].value = value;
m.entries[idx].occupied = true;
m.len = m.len + 1;
}
return false;
}
func StringMap_Len<V>(m: *StringMap<V>) -> uint {
return m.len;
}
func StringMap_Get<V>(m: *StringMap<V>, key: String) -> V {
let hash: uint = bux_hash_string(key);
var idx: uint = hash % m.cap;
while m.entries[idx].occupied {
if String_Eq(m.entries[idx].key, key) {
return m.entries[idx].value;
}
idx = (idx + 1) % m.cap;
}
var zero: V = 0 as V;
return zero;
}
func StringMap_IsEmpty<V>(m: *StringMap<V>) -> bool {
return m.len == 0;
}
func StringMap_Remove<V>(m: *StringMap<V>, key: String) -> bool {
if !StringMap_Has<V>(m, key) {
func StringMap_Has<V>(m: *StringMap<V>, key: String) -> bool {
let hash: uint = bux_hash_string(key);
var idx: uint = hash % m.cap;
while m.entries[idx].occupied {
if String_Eq(m.entries[idx].key, key) {
return true;
}
idx = (idx + 1) % m.cap;
}
return false;
}
var fresh: StringMap<V> = StringMap_New<V>(m.cap);
var i: uint = 0;
while i < m.cap {
if m.entries[i].occupied {
if !String_Eq(m.entries[i].key, key) {
StringMap_Set<V>(&fresh, m.entries[i].key, m.entries[i].value);
}
func StringMap_Len<V>(m: *StringMap<V>) -> uint {
return m.len;
}
func StringMap_IsEmpty<V>(m: *StringMap<V>) -> bool {
return m.len == 0;
}
func StringMap_Remove<V>(m: *StringMap<V>, key: String) -> bool {
if !StringMap_Has<V>(m, key) {
return false;
}
i = i + 1;
var fresh: StringMap<V> = StringMap_New<V>(m.cap);
var i: uint = 0;
while i < m.cap {
if m.entries[i].occupied {
if !String_Eq(m.entries[i].key, key) {
StringMap_Set<V>(&fresh, m.entries[i].key, m.entries[i].value);
}
}
i = i + 1;
}
bux_free(m.entries as *void);
m.entries = fresh.entries;
m.cap = fresh.cap;
m.len = fresh.len;
// Ownership transferred to `m` — clear `fresh` so auto-Drop does not free twice
fresh.entries = null as *StringMapEntry<V>;
fresh.cap = 0;
fresh.len = 0;
return true;
}
bux_free(m.entries as *void);
m.entries = fresh.entries;
m.cap = fresh.cap;
m.len = fresh.len;
return true;
}
func StringMap_Clear<V>(m: *StringMap<V>) {
var i: uint = 0;
while i < m.cap {
m.entries[i].occupied = false;
i = i + 1;
func StringMap_Clear<V>(m: *StringMap<V>) {
var i: uint = 0;
while i < m.cap {
m.entries[i].occupied = false;
i = i + 1;
}
m.len = 0;
}
m.len = 0;
}
func StringMap_Free<V>(m: *StringMap<V>) {
bux_free(m.entries as *void);
m.entries = null as *StringMapEntry<V>;
m.cap = 0;
m.len = 0;
}
func StringMap_Free<V>(m: *StringMap<V>) {
bux_free(m.entries as *void);
m.entries = null as *StringMapEntry<V>;
m.cap = 0;
m.len = 0;
}
}
}
+40 -40
View File
@@ -1,44 +1,44 @@
module Std::Math {
extern func bux_sqrt(x: float64) -> float64;
extern func bux_pow(x: float64, y: float64) -> float64;
extern func bux_abs_i64(x: int64) -> int64;
extern func bux_abs_f64(x: float64) -> float64;
extern func bux_min_i64(a: int64, b: int64) -> int64;
extern func bux_max_i64(a: int64, b: int64) -> int64;
extern func bux_min_f64(a: float64, b: float64) -> float64;
extern func bux_max_f64(a: float64, b: float64) -> float64;
extern func bux_sqrt(x: float64) -> float64;
extern func bux_pow(x: float64, y: float64) -> float64;
extern func bux_abs_i64(x: int64) -> int64;
extern func bux_abs_f64(x: float64) -> float64;
extern func bux_min_i64(a: int64, b: int64) -> int64;
extern func bux_max_i64(a: int64, b: int64) -> int64;
extern func bux_min_f64(a: float64, b: float64) -> float64;
extern func bux_max_f64(a: float64, b: float64) -> float64;
func Sqrt(x: float64) -> float64 {
return bux_sqrt(x);
}
func Pow(x: float64, y: float64) -> float64 {
return bux_pow(x, y);
}
func Abs(n: int64) -> int64 {
return bux_abs_i64(n);
}
func AbsF(f: float64) -> float64 {
return bux_abs_f64(f);
}
func Min(a: int64, b: int64) -> int64 {
return bux_min_i64(a, b);
}
func Max(a: int64, b: int64) -> int64 {
return bux_max_i64(a, b);
}
func MinF(a: float64, b: float64) -> float64 {
return bux_min_f64(a, b);
}
func MaxF(a: float64, b: float64) -> float64 {
return bux_max_f64(a, b);
}
func Sqrt(x: float64) -> float64 {
return bux_sqrt(x);
}
func Pow(x: float64, y: float64) -> float64 {
return bux_pow(x, y);
}
func Abs(n: int64) -> int64 {
return bux_abs_i64(n);
}
func AbsF(f: float64) -> float64 {
return bux_abs_f64(f);
}
func Min(a: int64, b: int64) -> int64 {
return bux_min_i64(a, b);
}
func Max(a: int64, b: int64) -> int64 {
return bux_max_i64(a, b);
}
func MinF(a: float64, b: float64) -> float64 {
return bux_min_f64(a, b);
}
func MaxF(a: float64, b: float64) -> float64 {
return bux_max_f64(a, b);
}
}
+20 -20
View File
@@ -1,29 +1,29 @@
module Std::Mem {
extern func bux_alloc(size: uint) -> *void;
extern func bux_realloc(ptr: *void, size: uint) -> *void;
extern func bux_free(ptr: *void);
extern func bux_mem_eq(a: *void, b: *void, size: uint) -> int;
extern func bux_alloc(size: uint) -> *void;
extern func bux_realloc(ptr: *void, size: uint) -> *void;
extern func bux_free(ptr: *void);
extern func bux_mem_eq(a: *void, b: *void, size: uint) -> int;
func Alloc(size: uint) -> *void {
return bux_alloc(size);
}
func Alloc(size: uint) -> *void {
return bux_alloc(size);
}
func Realloc(ptr: *void, size: uint) -> *void {
return bux_realloc(ptr, size);
}
func Realloc(ptr: *void, size: uint) -> *void {
return bux_realloc(ptr, size);
}
func Free(ptr: *void) {
bux_free(ptr);
}
func Free(ptr: *void) {
bux_free(ptr);
}
func MemEq(a: *void, b: *void, size: uint) -> bool {
return bux_mem_eq(a, b, size) != 0;
}
func MemEq(a: *void, b: *void, size: uint) -> bool {
return bux_mem_eq(a, b, size) != 0;
}
func New<T>() -> *T {
let sz: uint = sizeof(T);
return bux_alloc(sz) as *T;
}
func New<T>() -> *T {
let sz: uint = sizeof(T);
return bux_alloc(sz) as *T;
}
}
+50 -50
View File
@@ -1,62 +1,62 @@
module Std::Net {
extern func bux_socket_create() -> int;
extern func bux_socket_reuse(fd: int) -> int;
extern func bux_socket_bind(fd: int, addr: String, port: int) -> int;
extern func bux_socket_listen(fd: int, backlog: int) -> int;
extern func bux_socket_accept(fd: int) -> int;
extern func bux_socket_connect(fd: int, addr: String, port: int) -> int;
extern func bux_socket_send(fd: int, data: String, len: int) -> int;
extern func bux_socket_recv(fd: int, maxLen: int) -> String;
extern func bux_socket_close(fd: int) -> int;
extern func bux_socket_error() -> String;
extern func bux_socket_create() -> int;
extern func bux_socket_reuse(fd: int) -> int;
extern func bux_socket_bind(fd: int, addr: String, port: int) -> int;
extern func bux_socket_listen(fd: int, backlog: int) -> int;
extern func bux_socket_accept(fd: int) -> int;
extern func bux_socket_connect(fd: int, addr: String, port: int) -> int;
extern func bux_socket_send(fd: int, data: String, len: int) -> int;
extern func bux_socket_recv(fd: int, maxLen: int) -> String;
extern func bux_socket_close(fd: int) -> int;
extern func bux_socket_error() -> String;
/* Create a TCP socket. Returns -1 on error. */
func Net_Create() -> int {
return bux_socket_create();
}
/* Create a TCP socket. Returns -1 on error. */
func Net_Create() -> int {
return bux_socket_create();
}
/* Enable SO_REUSEADDR on a socket. */
func Net_SetReuse(fd: int) -> bool {
return bux_socket_reuse(fd) == 0;
}
/* Enable SO_REUSEADDR on a socket. */
func Net_SetReuse(fd: int) -> bool {
return bux_socket_reuse(fd) == 0;
}
/* Bind a socket to an address and port. */
func Net_Bind(fd: int, addr: String, port: int) -> bool {
return bux_socket_bind(fd, addr, port) == 0;
}
/* Bind a socket to an address and port. */
func Net_Bind(fd: int, addr: String, port: int) -> bool {
return bux_socket_bind(fd, addr, port) == 0;
}
/* Start listening for connections. */
func Net_Listen(fd: int, backlog: int) -> bool {
return bux_socket_listen(fd, backlog) == 0;
}
/* Start listening for connections. */
func Net_Listen(fd: int, backlog: int) -> bool {
return bux_socket_listen(fd, backlog) == 0;
}
/* Accept a connection. Returns new fd or -1 on error. */
func Net_Accept(fd: int) -> int {
return bux_socket_accept(fd);
}
/* Accept a connection. Returns new fd or -1 on error. */
func Net_Accept(fd: int) -> int {
return bux_socket_accept(fd);
}
/* Connect to a remote address and port. */
func Net_Connect(fd: int, addr: String, port: int) -> bool {
return bux_socket_connect(fd, addr, port) == 0;
}
/* Connect to a remote address and port. */
func Net_Connect(fd: int, addr: String, port: int) -> bool {
return bux_socket_connect(fd, addr, port) == 0;
}
/* Send data. Returns bytes sent or -1 on error. */
func Net_Send(fd: int, data: String) -> int {
return bux_socket_send(fd, data, bux_strlen(data) as int);
}
/* Send data. Returns bytes sent or -1 on error. */
func Net_Send(fd: int, data: String) -> int {
return bux_socket_send(fd, data, bux_strlen(data) as int);
}
/* Receive up to maxLen bytes. Returns empty string on error/EOF. */
func Net_Recv(fd: int, maxLen: int) -> String {
return bux_socket_recv(fd, maxLen);
}
/* Receive up to maxLen bytes. Returns empty string on error/EOF. */
func Net_Recv(fd: int, maxLen: int) -> String {
return bux_socket_recv(fd, maxLen);
}
/* Close a socket. */
func Net_Close(fd: int) -> bool {
return bux_socket_close(fd) == 0;
}
/* Close a socket. */
func Net_Close(fd: int) -> bool {
return bux_socket_close(fd) == 0;
}
/* Get last socket error as a string. */
func Net_LastError() -> String {
return bux_socket_error();
}
/* Get last socket error as a string. */
func Net_LastError() -> String {
return bux_socket_error();
}
}
+52 -52
View File
@@ -1,61 +1,61 @@
module Std::Option {
import Std::Io::{PrintLine};
import Std::Io::{PrintLine};
extern func bux_exit(code: int);
extern func bux_exit(code: int);
enum Option {
Some(int),
None,
}
func Option_NewSome(value: int) -> Option {
let o: Option = Option { tag: Option_Some };
o.data.Some_0 = value;
return o;
}
func Option_NewNone() -> Option {
return Option { tag: Option_None };
}
func Option_IsSome(o: Option) -> bool {
return o.tag == Option_Some;
}
func Option_IsNone(o: Option) -> bool {
return o.tag == Option_None;
}
func Option_Unwrap(o: Option) -> int {
if o.tag != Option_Some {
PrintLine("panic: unwrap on None");
return 0;
enum Option {
Some(int),
None,
}
return o.data.Some_0;
}
func Option_UnwrapOr(o: Option, fallback: int) -> int {
if o.tag == Option_Some {
return o.data.Some_0;
}
return fallback;
}
/* Unwrap Some or panic with a custom message */
func Option_Expect(o: Option, msg: String) -> int {
if o.tag != Option_Some {
PrintLine(msg);
bux_exit(1);
}
return o.data.Some_0;
}
/* If o is Some return it, otherwise return other */
func Option_Or(o: Option, other: Option) -> Option {
if o.tag == Option_Some {
func Option_NewSome(value: int) -> Option {
let o: Option = Option { tag: Option_Some };
o.data.Some_0 = value;
return o;
}
return other;
}
func Option_NewNone() -> Option {
return Option { tag: Option_None };
}
func Option_IsSome(o: Option) -> bool {
return o.tag == Option_Some;
}
func Option_IsNone(o: Option) -> bool {
return o.tag == Option_None;
}
func Option_Unwrap(o: Option) -> int {
if o.tag != Option_Some {
PrintLine("panic: unwrap on None");
return 0;
}
return o.data.Some_0;
}
func Option_UnwrapOr(o: Option, fallback: int) -> int {
if o.tag == Option_Some {
return o.data.Some_0;
}
return fallback;
}
/* Unwrap Some or panic with a custom message */
func Option_Expect(o: Option, msg: String) -> int {
if o.tag != Option_Some {
PrintLine(msg);
bux_exit(1);
}
return o.data.Some_0;
}
/* If o is Some return it, otherwise return other */
func Option_Or(o: Option, other: Option) -> Option {
if o.tag == Option_Some {
return o;
}
return other;
}
}
+29 -29
View File
@@ -1,40 +1,40 @@
module Std::Os {
extern func bux_argc() -> int;
extern func bux_argv(index: int) -> String;
extern func bux_getenv(name: String) -> String;
extern func bux_setenv(name: String, value: String) -> int;
extern func bux_getcwd() -> String;
extern func bux_chdir(path: String) -> int;
extern func bux_exit(code: int);
extern func bux_argc() -> int;
extern func bux_argv(index: int) -> String;
extern func bux_getenv(name: String) -> String;
extern func bux_setenv(name: String, value: String) -> int;
extern func bux_getcwd() -> String;
extern func bux_chdir(path: String) -> int;
extern func bux_exit(code: int);
func Os_ArgsCount() -> int {
return bux_argc();
}
func Os_ArgsCount() -> int {
return bux_argc();
}
func Os_Args(index: int) -> String {
return bux_argv(index);
}
func Os_Args(index: int) -> String {
return bux_argv(index);
}
func Os_GetEnv(name: String) -> String {
return bux_getenv(name);
}
func Os_GetEnv(name: String) -> String {
return bux_getenv(name);
}
func Os_SetEnv(name: String, value: String) -> bool {
return bux_setenv(name, value) == 0;
}
func Os_SetEnv(name: String, value: String) -> bool {
return bux_setenv(name, value) == 0;
}
func Os_GetCwd() -> String {
return bux_getcwd();
}
func Os_GetCwd() -> String {
return bux_getcwd();
}
func Os_Chdir(path: String) -> bool {
return bux_chdir(path) == 0;
}
func Os_Chdir(path: String) -> bool {
return bux_chdir(path) == 0;
}
/* Terminate the process with the given exit code */
func Os_Exit(code: int) {
bux_exit(code);
}
/* Terminate the process with the given exit code */
func Os_Exit(code: int) {
bux_exit(code);
}
}
+15 -15
View File
@@ -1,19 +1,19 @@
module Std::Path {
extern func bux_path_join(a: String, b: String) -> String;
extern func bux_path_parent(path: String) -> String;
extern func bux_path_ext(path: String) -> String;
extern func bux_path_join(a: String, b: String) -> String;
extern func bux_path_parent(path: String) -> String;
extern func bux_path_ext(path: String) -> String;
func Path_Join(a: String, b: String) -> String {
return bux_path_join(a, b);
}
func Path_Parent(path: String) -> String {
return bux_path_parent(path);
}
func Path_Ext(path: String) -> String {
return bux_path_ext(path);
}
func Path_Join(a: String, b: String) -> String {
return bux_path_join(a, b);
}
func Path_Parent(path: String) -> String {
return bux_path_parent(path);
}
func Path_Ext(path: String) -> String {
return bux_path_ext(path);
}
}
+8 -8
View File
@@ -1,14 +1,14 @@
module Std::Process {
extern func bux_process_run(cmd: String) -> int;
extern func bux_process_output(cmd: String) -> String;
extern func bux_process_run(cmd: String) -> int;
extern func bux_process_output(cmd: String) -> String;
func Process_Run(cmd: String) -> int {
return bux_process_run(cmd);
}
func Process_Run(cmd: String) -> int {
return bux_process_run(cmd);
}
func Process_Output(cmd: String) -> String {
return bux_process_output(cmd);
}
func Process_Output(cmd: String) -> String {
return bux_process_output(cmd);
}
}
+63 -63
View File
@@ -1,72 +1,72 @@
module Std::Result {
import Std::Io::{PrintLine};
import Std::Io::{PrintLine};
extern func bux_exit(code: int);
extern func bux_exit(code: int);
enum Result {
Ok(int),
Err(String),
}
func Result_NewOk(value: int) -> Result {
let r: Result = Result { tag: Result_Ok };
r.data.Ok_0 = value;
return r;
}
func Result_NewErr(msg: String) -> Result {
let r: Result = Result { tag: Result_Err };
r.data.Err_0 = msg;
return r;
}
func Result_IsOk(r: Result) -> bool {
return r.tag == Result_Ok;
}
func Result_IsErr(r: Result) -> bool {
return r.tag == Result_Err;
}
func Result_Unwrap(r: Result) -> int {
if r.tag != Result_Ok {
PrintLine("panic: unwrap on Err");
return 0;
enum Result {
Ok(int),
Err(String),
}
return r.data.Ok_0;
}
func Result_UnwrapOr(r: Result, fallback: int) -> int {
if r.tag == Result_Ok {
return r.data.Ok_0;
}
return fallback;
}
/* Unwrap Ok or panic with a custom message */
func Result_Expect(r: Result, msg: String) -> int {
if r.tag != Result_Ok {
PrintLine(msg);
bux_exit(1);
}
return r.data.Ok_0;
}
/* Extract Err payload (panics if Ok) */
func Result_UnwrapErr(r: Result) -> String {
if r.tag != Result_Err {
PrintLine("panic: unwrap_err on Ok");
return "";
}
return r.data.Err_0;
}
/* If r is Ok return it, otherwise return other */
func Result_Or(r: Result, other: Result) -> Result {
if r.tag == Result_Ok {
func Result_NewOk(value: int) -> Result {
let r: Result = Result { tag: Result_Ok };
r.data.Ok_0 = value;
return r;
}
return other;
}
func Result_NewErr(msg: String) -> Result {
let r: Result = Result { tag: Result_Err };
r.data.Err_0 = msg;
return r;
}
func Result_IsOk(r: Result) -> bool {
return r.tag == Result_Ok;
}
func Result_IsErr(r: Result) -> bool {
return r.tag == Result_Err;
}
func Result_Unwrap(r: Result) -> int {
if r.tag != Result_Ok {
PrintLine("panic: unwrap on Err");
return 0;
}
return r.data.Ok_0;
}
func Result_UnwrapOr(r: Result, fallback: int) -> int {
if r.tag == Result_Ok {
return r.data.Ok_0;
}
return fallback;
}
/* Unwrap Ok or panic with a custom message */
func Result_Expect(r: Result, msg: String) -> int {
if r.tag != Result_Ok {
PrintLine(msg);
bux_exit(1);
}
return r.data.Ok_0;
}
/* Extract Err payload (panics if Ok) */
func Result_UnwrapErr(r: Result) -> String {
if r.tag != Result_Err {
PrintLine("panic: unwrap_err on Ok");
return "";
}
return r.data.Err_0;
}
/* If r is Ok return it, otherwise return other */
func Result_Or(r: Result, other: Result) -> Result {
if r.tag == Result_Ok {
return r;
}
return other;
}
}
+95 -91
View File
@@ -1,112 +1,116 @@
module Std::Set {
extern func bux_hash_bytes(ptr: *void, size: uint) -> uint;
extern func bux_mem_eq(a: *void, b: *void, size: uint) -> int;
extern func bux_alloc(size: uint) -> *void;
extern func bux_free(ptr: *void);
extern func bux_hash_bytes(ptr: *void, size: uint) -> uint;
extern func bux_mem_eq(a: *void, b: *void, size: uint) -> int;
extern func bux_alloc(size: uint) -> *void;
extern func bux_free(ptr: *void);
struct SetEntry<T> {
value: T,
occupied: bool,
}
struct Set<T> {
entries: *SetEntry<T>,
cap: uint,
len: uint,
}
func Set_New<T>(cap: uint) -> Set<T> {
let total: uint = cap * sizeof(SetEntry<T>);
let data: *SetEntry<T> = bux_alloc(total) as *SetEntry<T>;
var i: uint = 0;
while i < cap {
data[i].occupied = false;
i = i + 1;
struct SetEntry<T> {
value: T,
occupied: bool,
}
return Set<T> { entries: data, cap: cap, len: 0 };
}
func Set_Add<T>(s: *Set<T>, value: T) {
var valuePtr: *T = &value;
let hash: uint = bux_hash_bytes(valuePtr as *void, sizeof(T));
var idx: uint = hash % s.cap;
while s.entries[idx].occupied {
var entryPtr: *T = &s.entries[idx].value;
if bux_mem_eq(entryPtr as *void, valuePtr as *void, sizeof(T)) != 0 {
return;
struct Set<T> {
entries: *SetEntry<T>,
cap: uint,
len: uint,
}
func Set_New<T>(cap: uint) -> Set<T> {
let total: uint = cap * sizeof(SetEntry<T>);
let data: *SetEntry<T> = bux_alloc(total) as *SetEntry<T>;
var i: uint = 0;
while i < cap {
data[i].occupied = false;
i = i + 1;
}
idx = (idx + 1) % s.cap;
return Set<T> { entries: data, cap: cap, len: 0 };
}
s.entries[idx].value = value;
s.entries[idx].occupied = true;
s.len = s.len + 1;
}
func Set_Has<T>(s: *Set<T>, value: T) -> bool {
var valuePtr: *T = &value;
let hash: uint = bux_hash_bytes(valuePtr as *void, sizeof(T));
var idx: uint = hash % s.cap;
while s.entries[idx].occupied {
var entryPtr: *T = &s.entries[idx].value;
if bux_mem_eq(entryPtr as *void, valuePtr as *void, sizeof(T)) != 0 {
return true;
func Set_Add<T>(s: *Set<T>, value: T) {
var valuePtr: *T = &value;
let hash: uint = bux_hash_bytes(valuePtr as *void, sizeof(T));
var idx: uint = hash % s.cap;
while s.entries[idx].occupied {
var entryPtr: *T = &s.entries[idx].value;
if bux_mem_eq(entryPtr as *void, valuePtr as *void, sizeof(T)) != 0 {
return;
}
idx = (idx + 1) % s.cap;
}
idx = (idx + 1) % s.cap;
s.entries[idx].value = value;
s.entries[idx].occupied = true;
s.len = s.len + 1;
}
return false;
}
func Set_Len<T>(s: *Set<T>) -> uint {
return s.len;
}
func Set_IsEmpty<T>(s: *Set<T>) -> bool {
return s.len == 0;
}
/* Remove value if present. Rebuilds the table to keep open-addressing correct. */
func Set_Remove<T>(s: *Set<T>, value: T) -> bool {
if !Set_Has<T>(s, value) {
func Set_Has<T>(s: *Set<T>, value: T) -> bool {
var valuePtr: *T = &value;
let hash: uint = bux_hash_bytes(valuePtr as *void, sizeof(T));
var idx: uint = hash % s.cap;
while s.entries[idx].occupied {
var entryPtr: *T = &s.entries[idx].value;
if bux_mem_eq(entryPtr as *void, valuePtr as *void, sizeof(T)) != 0 {
return true;
}
idx = (idx + 1) % s.cap;
}
return false;
}
var fresh: Set<T> = Set_New<T>(s.cap);
var i: uint = 0;
while i < s.cap {
if s.entries[i].occupied {
var entryPtr: *T = &s.entries[i].value;
var valuePtr: *T = &value;
if bux_mem_eq(entryPtr as *void, valuePtr as *void, sizeof(T)) == 0 {
Set_Add<T>(&fresh, s.entries[i].value);
}
func Set_Len<T>(s: *Set<T>) -> uint {
return s.len;
}
func Set_IsEmpty<T>(s: *Set<T>) -> bool {
return s.len == 0;
}
/* Remove value if present. Rebuilds the table to keep open-addressing correct. */
func Set_Remove<T>(s: *Set<T>, value: T) -> bool {
if !Set_Has<T>(s, value) {
return false;
}
i = i + 1;
var fresh: Set<T> = Set_New<T>(s.cap);
var i: uint = 0;
while i < s.cap {
if s.entries[i].occupied {
var entryPtr: *T = &s.entries[i].value;
var valuePtr: *T = &value;
if bux_mem_eq(entryPtr as *void, valuePtr as *void, sizeof(T)) == 0 {
Set_Add<T>(&fresh, s.entries[i].value);
}
}
i = i + 1;
}
bux_free(s.entries as *void);
s.entries = fresh.entries;
s.cap = fresh.cap;
s.len = fresh.len;
// Ownership transferred to `s` — clear `fresh` so auto-Drop does not free twice
fresh.entries = null as *SetEntry<T>;
fresh.cap = 0;
fresh.len = 0;
return true;
}
bux_free(s.entries as *void);
s.entries = fresh.entries;
s.cap = fresh.cap;
s.len = fresh.len;
return true;
}
func Set_Clear<T>(s: *Set<T>) {
var i: uint = 0;
while i < s.cap {
s.entries[i].occupied = false;
i = i + 1;
func Set_Clear<T>(s: *Set<T>) {
var i: uint = 0;
while i < s.cap {
s.entries[i].occupied = false;
i = i + 1;
}
s.len = 0;
}
s.len = 0;
}
func Set_Free<T>(s: *Set<T>) {
bux_free(s.entries as *void);
s.entries = null as *SetEntry<T>;
s.cap = 0;
s.len = 0;
}
func Set_Free<T>(s: *Set<T>) {
bux_free(s.entries as *void);
s.entries = null as *SetEntry<T>;
s.cap = 0;
s.len = 0;
}
func Set_Drop<T>(s: *Set<T>) {
Set_Free<T>(s);
}
func Set_Drop<T>(s: *Set<T>) {
Set_Free<T>(s);
}
}
+28 -28
View File
@@ -1,39 +1,39 @@
module Std::Slice {
extern func bux_bounds_check(index: uint, len: uint);
extern func bux_bounds_check(index: uint, len: uint);
struct Slice<T> {
data: *T,
len: uint,
}
struct Slice<T> {
data: *T,
len: uint,
}
func Slice_FromArray<T>(arr: *Array<T>) -> Slice<T> {
var s: Slice<T>;
s.data = arr.data;
s.len = arr.len;
return s;
}
func Slice_FromArray<T>(arr: *Array<T>) -> Slice<T> {
var s: Slice<T>;
s.data = arr.data;
s.len = arr.len;
return s;
}
func Slice_Get<T>(self: *Slice<T>, idx: uint) -> T {
bux_bounds_check(idx, self.len);
return self.data[idx];
}
func Slice_Get<T>(self: *Slice<T>, idx: uint) -> T {
bux_bounds_check(idx, self.len);
return self.data[idx];
}
func Slice_Set<T>(self: *Slice<T>, idx: uint, value: T) {
bux_bounds_check(idx, self.len);
self.data[idx] = value;
}
func Slice_Set<T>(self: *Slice<T>, idx: uint, value: T) {
bux_bounds_check(idx, self.len);
self.data[idx] = value;
}
func Slice_Len<T>(self: *Slice<T>) -> uint {
return self.len;
}
func Slice_Len<T>(self: *Slice<T>) -> uint {
return self.len;
}
func Slice_operator_index_get<T>(self: *Slice<T>, idx: uint) -> T {
return Slice_Get<T>(self, idx);
}
func Slice_operator_index_get<T>(self: *Slice<T>, idx: uint) -> T {
return Slice_Get<T>(self, idx);
}
func Slice_operator_index_set<T>(self: *Slice<T>, idx: uint, value: T) {
Slice_Set<T>(self, idx, value);
}
func Slice_operator_index_set<T>(self: *Slice<T>, idx: uint, value: T) {
Slice_Set<T>(self, idx, value);
}
}
+270 -261
View File
@@ -1,288 +1,297 @@
module Std::String {
extern func bux_strlen(s: String) -> uint;
extern func bux_strcmp(a: String, b: String) -> int;
extern func bux_strncmp(a: String, b: String, n: uint) -> int;
extern func bux_strcpy(dest: *char8, src: String) -> *char8;
extern func bux_strcat(dest: *char8, src: String) -> *char8;
extern func bux_strncpy(dest: *char8, src: String, n: uint) -> *char8;
extern func bux_strstr(haystack: String, needle: String) -> String;
extern func bux_str_contains(haystack: String, needle: String) -> int;
extern func bux_str_offset(pos: String, base: String) -> uint;
extern func bux_str_is_null(s: String) -> int;
extern func bux_str_slice(s: String, start: uint, len: uint) -> String;
extern func bux_str_trim_left(s: String) -> String;
extern func bux_str_trim_right(s: String) -> String;
extern func bux_str_trim(s: String) -> String;
extern func bux_int_to_str(n: int64) -> String;
extern func bux_str_to_int(s: String) -> int64;
extern func bux_sb_new(initial_cap: uint) -> *void;
extern func bux_sb_append(sb: *void, s: String);
extern func bux_sb_append_int(sb: *void, n: int64);
extern func bux_sb_append_float(sb: *void, f: float64);
extern func bux_sb_append_char(sb: *void, c: char8);
extern func bux_sb_build(sb: *void) -> String;
extern func bux_sb_free(sb: *void);
extern func bux_str_split_count(s: String, delim: String) -> uint;
extern func bux_str_split_part(s: String, delim: String, index: uint) -> String;
extern func bux_str_join2(a: String, b: String, sep: String) -> String;
extern func bux_float_to_string(f: float64) -> String;
extern func bux_str_format(pattern: String, a0: String, a1: String, a2: String, a3: String, a4: String, a5: String, a6: String, a7: String) -> String;
extern func bux_strlen(s: String) -> uint;
extern func bux_strcmp(a: String, b: String) -> int;
extern func bux_strncmp(a: String, b: String, n: uint) -> int;
extern func bux_strcpy(dest: *char8, src: String) -> *char8;
extern func bux_strcat(dest: *char8, src: String) -> *char8;
extern func bux_strncpy(dest: *char8, src: String, n: uint) -> *char8;
extern func bux_strstr(haystack: String, needle: String) -> String;
extern func bux_str_contains(haystack: String, needle: String) -> int;
extern func bux_str_offset(pos: String, base: String) -> uint;
extern func bux_str_is_null(s: String) -> int;
extern func bux_str_slice(s: String, start: uint, len: uint) -> String;
extern func bux_str_trim_left(s: String) -> String;
extern func bux_str_trim_right(s: String) -> String;
extern func bux_str_trim(s: String) -> String;
extern func bux_int_to_str(n: int64) -> String;
extern func bux_str_to_int(s: String) -> int64;
extern func bux_sb_new(initial_cap: uint) -> *void;
extern func bux_sb_append(sb: *void, s: String);
extern func bux_sb_append_int(sb: *void, n: int64);
extern func bux_sb_append_float(sb: *void, f: float64);
extern func bux_sb_append_char(sb: *void, c: char8);
extern func bux_sb_build(sb: *void) -> String;
extern func bux_sb_free(sb: *void);
extern func bux_str_split_count(s: String, delim: String) -> uint;
extern func bux_str_split_part(s: String, delim: String, index: uint) -> String;
extern func bux_str_join2(a: String, b: String, sep: String) -> String;
extern func bux_float_to_string(f: float64) -> String;
extern func bux_str_format(pattern: String, a0: String, a1: String, a2: String, a3: String, a4: String, a5: String, a6: String, a7: String) -> String;
func String_Len(s: String) -> uint {
return bux_strlen(s);
}
func String_IsEmpty(s: String) -> bool {
return bux_strlen(s) == 0;
}
func String_IsNull(s: String) -> bool {
return bux_str_is_null(s) != 0;
}
func String_Eq(a: String, b: String) -> bool {
return bux_strcmp(a, b) == 0;
}
func String_Concat(a: String, b: String) -> String {
let len_a: uint = bux_strlen(a);
let len_b: uint = bux_strlen(b);
let total: uint = len_a + len_b + 1;
let buf: *char8 = bux_alloc(total) as *char8;
bux_strcpy(buf, a);
bux_strcat(buf, b);
return buf;
}
func String_Copy(s: String) -> String {
let len: uint = bux_strlen(s);
let buf: *char8 = bux_alloc(len + 1) as *char8;
bux_strcpy(buf, s);
return buf;
}
func String_StartsWith(s: String, prefix: String) -> bool {
let s_len: uint = bux_strlen(s);
let p_len: uint = bux_strlen(prefix);
if p_len > s_len {
return false;
/// Byte length of a C string (`strlen`).
func String_Len(s: String) -> uint {
return bux_strlen(s);
}
let r: int = bux_strncmp(s, prefix, p_len);
return r == 0;
}
func String_EndsWith(s: String, suffix: String) -> bool {
let s_len: uint = bux_strlen(s);
let suf_len: uint = bux_strlen(suffix);
if suf_len > s_len {
return false;
/// True if the string has zero length.
func String_IsEmpty(s: String) -> bool {
return bux_strlen(s) == 0;
}
let start: uint = s_len - suf_len;
let tail: String = bux_str_slice(s, start, suf_len);
let eq: bool = bux_strcmp(tail, suffix) == 0;
return eq;
}
func String_Contains(s: String, substr: String) -> bool {
let r: int = bux_str_contains(s, substr);
return r != 0;
}
/// True if the pointer is null.
func String_IsNull(s: String) -> bool {
return bux_str_is_null(s) != 0;
}
func String_Slice(s: String, start: uint, len: uint) -> String {
return bux_str_slice(s, start, len);
}
/// Lexicographic equality.
func String_Eq(a: String, b: String) -> bool {
return bux_strcmp(a, b) == 0;
}
func String_Trim(s: String) -> String {
return bux_str_trim(s);
}
/// Allocate and return `a` concatenated with `b`.
func String_Concat(a: String, b: String) -> String {
let len_a: uint = bux_strlen(a);
let len_b: uint = bux_strlen(b);
let total: uint = len_a + len_b + 1;
let buf: *char8 = bux_alloc(total) as *char8;
bux_strcpy(buf, a);
bux_strcat(buf, b);
return buf;
}
func String_TrimLeft(s: String) -> String {
return bux_str_trim_left(s);
}
/// Heap-copy of `s`.
func String_Copy(s: String) -> String {
let len: uint = bux_strlen(s);
let buf: *char8 = bux_alloc(len + 1) as *char8;
bux_strcpy(buf, s);
return buf;
}
func String_TrimRight(s: String) -> String {
return bux_str_trim_right(s);
}
func String_FromInt(n: int64) -> String {
return bux_int_to_str(n);
}
func String_ToInt(s: String) -> int64 {
return bux_str_to_int(s);
}
// String Builder — efficient string construction
struct StringBuilder {
handle: *void,
}
func StringBuilder_New() -> StringBuilder {
return StringBuilder { handle: bux_sb_new(64) };
}
func StringBuilder_NewCap(cap: uint) -> StringBuilder {
return StringBuilder { handle: bux_sb_new(cap) };
}
func StringBuilder_Append(sb: *StringBuilder, s: String) {
bux_sb_append(sb.handle, s);
}
func StringBuilder_AppendInt(sb: *StringBuilder, n: int64) {
bux_sb_append_int(sb.handle, n);
}
func StringBuilder_AppendFloat(sb: *StringBuilder, f: float64) {
bux_sb_append_float(sb.handle, f);
}
func StringBuilder_AppendChar(sb: *StringBuilder, c: char8) {
bux_sb_append_char(sb.handle, c);
}
func StringBuilder_Build(sb: *StringBuilder) -> String {
return bux_sb_build(sb.handle);
}
func StringBuilder_Free(sb: *StringBuilder) {
bux_sb_free(sb.handle);
}
/* True if empty or only whitespace (space, tab, CR, LF) */
func String_IsBlank(s: String) -> bool {
let n: uint = bux_strlen(s);
var i: uint = 0;
while i < n {
let ch: String = bux_str_slice(s, i, 1);
if !(String_Eq(ch, " ") || String_Eq(ch, "\t") || String_Eq(ch, "\n") || String_Eq(ch, "\r")) {
/// True if `s` begins with `prefix`.
func String_StartsWith(s: String, prefix: String) -> bool {
let s_len: uint = bux_strlen(s);
let p_len: uint = bux_strlen(prefix);
if p_len > s_len {
return false;
}
i = i + 1;
let r: int = bux_strncmp(s, prefix, p_len);
return r == 0;
}
return true;
}
/* Repeat s, count times (count==0 → empty string) */
func String_Repeat(s: String, count: uint) -> String {
if count == 0 {
return "";
}
if count == 1 {
return s;
}
var sb: StringBuilder = StringBuilder_New();
var i: uint = 0;
while i < count {
StringBuilder_Append(&sb, s);
i = i + 1;
}
let result: String = StringBuilder_Build(&sb);
StringBuilder_Free(&sb);
return result;
}
// ---------------------------------------------------------------------------
// String split/join
// ---------------------------------------------------------------------------
func String_SplitCount(s: String, delim: String) -> uint {
return bux_str_split_count(s, delim);
}
func String_SplitPart(s: String, delim: String, index: uint) -> String {
return bux_str_split_part(s, delim, index);
}
func String_Join2(a: String, b: String, sep: String) -> String {
return bux_str_join2(a, b, sep);
}
// ---------------------------------------------------------------------------
// String find/replace/format
// ---------------------------------------------------------------------------
// String_Chars — return single-character string at index (for iteration)
func String_Chars(s: String, index: uint) -> String {
return bux_str_slice(s, index, 1);
}
func String_Find(haystack: String, needle: String) -> String {
return bux_strstr(haystack, needle);
}
func String_Offset(pos: String, base: String) -> uint {
return bux_str_offset(pos, base);
}
func String_Replace(s: String, old: String, new: String) -> String {
let pos: String = bux_strstr(s, old);
if String_IsNull(pos) {
return s;
}
let oldLen: uint = bux_strlen(old);
let prefixLen: uint = String_Offset(pos, s);
let prefix: String = bux_str_slice(s, 0, prefixLen);
let suffix: String = bux_str_slice(s, prefixLen + oldLen, bux_strlen(s) - prefixLen - oldLen);
let temp: String = String_Concat(prefix, new);
let result: String = String_Concat(temp, suffix);
return result;
}
/* Replace every non-overlapping occurrence of old with new.
Empty old is a no-op (returns s unchanged). Safe if new contains old. */
func String_ReplaceAll(s: String, old: String, new: String) -> String {
let oldLen: uint = bux_strlen(old);
if oldLen == 0 {
return s;
}
var sb: StringBuilder = StringBuilder_New();
var remaining: String = s;
while true {
let pos: String = bux_strstr(remaining, old);
if String_IsNull(pos) {
StringBuilder_Append(&sb, remaining);
break;
/// True if `s` ends with `suffix`.
func String_EndsWith(s: String, suffix: String) -> bool {
let s_len: uint = bux_strlen(s);
let suf_len: uint = bux_strlen(suffix);
if suf_len > s_len {
return false;
}
let prefixLen: uint = String_Offset(pos, remaining);
let prefix: String = bux_str_slice(remaining, 0, prefixLen);
StringBuilder_Append(&sb, prefix);
StringBuilder_Append(&sb, new);
let remLen: uint = bux_strlen(remaining);
remaining = bux_str_slice(remaining, prefixLen + oldLen, remLen - prefixLen - oldLen);
let start: uint = s_len - suf_len;
let tail: String = bux_str_slice(s, start, suf_len);
let eq: bool = bux_strcmp(tail, suffix) == 0;
return eq;
}
let result: String = StringBuilder_Build(&sb);
StringBuilder_Free(&sb);
return result;
}
extern func bux_str_to_float(s: String) -> float64;
/// True if `substr` occurs anywhere in `s`.
func String_Contains(s: String, substr: String) -> bool {
let r: int = bux_str_contains(s, substr);
return r != 0;
}
func String_ToFloat(s: String) -> float64 {
return bux_str_to_float(s);
}
func String_Slice(s: String, start: uint, len: uint) -> String {
return bux_str_slice(s, start, len);
}
func String_FromBool(b: bool) -> String {
if b { return "true"; }
return "false";
}
func String_Trim(s: String) -> String {
return bux_str_trim(s);
}
func String_FromFloat(f: float64) -> String {
return bux_float_to_string(f);
}
func String_TrimLeft(s: String) -> String {
return bux_str_trim_left(s);
}
func String_Format1(pattern: String, a0: String) -> String {
return bux_str_format(pattern, a0, "", "", "", "", "", "", "");
}
func String_TrimRight(s: String) -> String {
return bux_str_trim_right(s);
}
func String_Format2(pattern: String, a0: String, a1: String) -> String {
return bux_str_format(pattern, a0, a1, "", "", "", "", "", "");
}
func String_FromInt(n: int64) -> String {
return bux_int_to_str(n);
}
func String_Format3(pattern: String, a0: String, a1: String, a2: String) -> String {
return bux_str_format(pattern, a0, a1, a2, "", "", "", "", "");
}
func String_ToInt(s: String) -> int64 {
return bux_str_to_int(s);
}
// String Builder — efficient string construction
struct StringBuilder {
handle: *void,
}
func StringBuilder_New() -> StringBuilder {
return StringBuilder { handle: bux_sb_new(64) };
}
func StringBuilder_NewCap(cap: uint) -> StringBuilder {
return StringBuilder { handle: bux_sb_new(cap) };
}
func StringBuilder_Append(sb: *StringBuilder, s: String) {
bux_sb_append(sb.handle, s);
}
func StringBuilder_AppendInt(sb: *StringBuilder, n: int64) {
bux_sb_append_int(sb.handle, n);
}
func StringBuilder_AppendFloat(sb: *StringBuilder, f: float64) {
bux_sb_append_float(sb.handle, f);
}
func StringBuilder_AppendChar(sb: *StringBuilder, c: char8) {
bux_sb_append_char(sb.handle, c);
}
func StringBuilder_Build(sb: *StringBuilder) -> String {
return bux_sb_build(sb.handle);
}
func StringBuilder_Free(sb: *StringBuilder) {
bux_sb_free(sb.handle);
}
/// True if empty or only whitespace (space, tab, CR, LF).
func String_IsBlank(s: String) -> bool {
let n: uint = bux_strlen(s);
var i: uint = 0;
while i < n {
let ch: String = bux_str_slice(s, i, 1);
if !(String_Eq(ch, " ") || String_Eq(ch, "\t") || String_Eq(ch, "\n") || String_Eq(ch, "\r")) {
return false;
}
i = i + 1;
}
return true;
}
/// Repeat `s`, `count` times (`count == 0` → empty string).
func String_Repeat(s: String, count: uint) -> String {
if count == 0 {
return "";
}
if count == 1 {
return s;
}
var sb: StringBuilder = StringBuilder_New();
var i: uint = 0;
while i < count {
StringBuilder_Append(&sb, s);
i = i + 1;
}
let result: String = StringBuilder_Build(&sb);
StringBuilder_Free(&sb);
return result;
}
// ---------------------------------------------------------------------------
// String split/join
// ---------------------------------------------------------------------------
func String_SplitCount(s: String, delim: String) -> uint {
return bux_str_split_count(s, delim);
}
func String_SplitPart(s: String, delim: String, index: uint) -> String {
return bux_str_split_part(s, delim, index);
}
func String_Join2(a: String, b: String, sep: String) -> String {
return bux_str_join2(a, b, sep);
}
// ---------------------------------------------------------------------------
// String find/replace/format
// ---------------------------------------------------------------------------
// String_Chars — return single-character string at index (for iteration)
func String_Chars(s: String, index: uint) -> String {
return bux_str_slice(s, index, 1);
}
func String_Find(haystack: String, needle: String) -> String {
return bux_strstr(haystack, needle);
}
func String_Offset(pos: String, base: String) -> uint {
return bux_str_offset(pos, base);
}
func String_Replace(s: String, old: String, new: String) -> String {
let pos: String = bux_strstr(s, old);
if String_IsNull(pos) {
return s;
}
let oldLen: uint = bux_strlen(old);
let prefixLen: uint = String_Offset(pos, s);
let prefix: String = bux_str_slice(s, 0, prefixLen);
let suffix: String = bux_str_slice(s, prefixLen + oldLen, bux_strlen(s) - prefixLen - oldLen);
let temp: String = String_Concat(prefix, new);
let result: String = String_Concat(temp, suffix);
return result;
}
/// Replace every non-overlapping occurrence of `old` with `new`.
/// Empty `old` is a no-op (returns `s` unchanged). Safe if `new` contains `old`.
func String_ReplaceAll(s: String, old: String, new: String) -> String {
let oldLen: uint = bux_strlen(old);
if oldLen == 0 {
return s;
}
var sb: StringBuilder = StringBuilder_New();
var remaining: String = s;
while true {
let pos: String = bux_strstr(remaining, old);
if String_IsNull(pos) {
StringBuilder_Append(&sb, remaining);
break;
}
let prefixLen: uint = String_Offset(pos, remaining);
let prefix: String = bux_str_slice(remaining, 0, prefixLen);
StringBuilder_Append(&sb, prefix);
StringBuilder_Append(&sb, new);
let remLen: uint = bux_strlen(remaining);
remaining = bux_str_slice(remaining, prefixLen + oldLen, remLen - prefixLen - oldLen);
}
let result: String = StringBuilder_Build(&sb);
StringBuilder_Free(&sb);
return result;
}
extern func bux_str_to_float(s: String) -> float64;
func String_ToFloat(s: String) -> float64 {
return bux_str_to_float(s);
}
func String_FromBool(b: bool) -> String {
if b { return "true"; }
return "false";
}
func String_FromFloat(f: float64) -> String {
return bux_float_to_string(f);
}
func String_Format1(pattern: String, a0: String) -> String {
return bux_str_format(pattern, a0, "", "", "", "", "", "", "");
}
func String_Format2(pattern: String, a0: String, a1: String) -> String {
return bux_str_format(pattern, a0, a1, "", "", "", "", "", "");
}
func String_Format3(pattern: String, a0: String, a1: String, a2: String) -> String {
return bux_str_format(pattern, a0, a1, a2, "", "", "", "", "");
}
}
+42 -42
View File
@@ -1,58 +1,58 @@
module Std::Sync {
extern func bux_mutex_new() -> *void;
extern func bux_mutex_lock(handle: *void);
extern func bux_mutex_unlock(handle: *void);
extern func bux_mutex_free(handle: *void);
extern func bux_mutex_new() -> *void;
extern func bux_mutex_lock(handle: *void);
extern func bux_mutex_unlock(handle: *void);
extern func bux_mutex_free(handle: *void);
extern func bux_rwlock_new() -> *void;
extern func bux_rwlock_rdlock(handle: *void);
extern func bux_rwlock_wrlock(handle: *void);
extern func bux_rwlock_unlock(handle: *void);
extern func bux_rwlock_free(handle: *void);
extern func bux_rwlock_new() -> *void;
extern func bux_rwlock_rdlock(handle: *void);
extern func bux_rwlock_wrlock(handle: *void);
extern func bux_rwlock_unlock(handle: *void);
extern func bux_rwlock_free(handle: *void);
struct Mutex {
handle: *void;
}
struct Mutex {
handle: *void;
}
struct RwLock {
handle: *void;
}
struct RwLock {
handle: *void;
}
func Mutex_New() -> Mutex {
return Mutex { handle: bux_mutex_new() };
}
func Mutex_New() -> Mutex {
return Mutex { handle: bux_mutex_new() };
}
func Mutex_Lock(m: *Mutex) {
bux_mutex_lock(m.handle);
}
func Mutex_Lock(m: *Mutex) {
bux_mutex_lock(m.handle);
}
func Mutex_Unlock(m: *Mutex) {
bux_mutex_unlock(m.handle);
}
func Mutex_Unlock(m: *Mutex) {
bux_mutex_unlock(m.handle);
}
func Mutex_Free(m: *Mutex) {
bux_mutex_free(m.handle);
}
func Mutex_Free(m: *Mutex) {
bux_mutex_free(m.handle);
}
func RwLock_New() -> RwLock {
return RwLock { handle: bux_rwlock_new() };
}
func RwLock_New() -> RwLock {
return RwLock { handle: bux_rwlock_new() };
}
func RwLock_ReadLock(rw: *RwLock) {
bux_rwlock_rdlock(rw.handle);
}
func RwLock_ReadLock(rw: *RwLock) {
bux_rwlock_rdlock(rw.handle);
}
func RwLock_WriteLock(rw: *RwLock) {
bux_rwlock_wrlock(rw.handle);
}
func RwLock_WriteLock(rw: *RwLock) {
bux_rwlock_wrlock(rw.handle);
}
func RwLock_Unlock(rw: *RwLock) {
bux_rwlock_unlock(rw.handle);
}
func RwLock_Unlock(rw: *RwLock) {
bux_rwlock_unlock(rw.handle);
}
func RwLock_Free(rw: *RwLock) {
bux_rwlock_free(rw.handle);
}
func RwLock_Free(rw: *RwLock) {
bux_rwlock_free(rw.handle);
}
}
+31 -31
View File
@@ -1,43 +1,43 @@
module Std::Task {
extern func bux_task_init(num_workers: int);
extern func bux_task_spawn(fn: *void, arg: *void) -> *void;
extern func bux_task_join(handle: *void);
extern func bux_task_sleep(ms: int64);
extern func bux_task_yield();
extern func bux_task_current_id() -> int;
extern func bux_task_shutdown();
extern func bux_task_init(num_workers: int);
extern func bux_task_spawn(fn: *void, arg: *void) -> *void;
extern func bux_task_join(handle: *void);
extern func bux_task_sleep(ms: int64);
extern func bux_task_yield();
extern func bux_task_current_id() -> int;
extern func bux_task_shutdown();
struct TaskHandle {
handle: *void;
}
struct TaskHandle {
handle: *void;
}
func Task_Init(num_workers: int) {
bux_task_init(num_workers);
}
func Task_Init(num_workers: int) {
bux_task_init(num_workers);
}
func Task_Spawn(fn: *void, arg: *void) -> TaskHandle {
return TaskHandle { handle: bux_task_spawn(fn, arg) };
}
func Task_Spawn(fn: *void, arg: *void) -> TaskHandle {
return TaskHandle { handle: bux_task_spawn(fn, arg) };
}
func Task_Wait(t: TaskHandle) {
bux_task_join(t.handle);
}
func Task_Wait(t: TaskHandle) {
bux_task_join(t.handle);
}
func Task_Sleep(ms: int64) {
bux_task_sleep(ms);
}
func Task_Sleep(ms: int64) {
bux_task_sleep(ms);
}
func Task_Yield() {
bux_task_yield();
}
func Task_Yield() {
bux_task_yield();
}
func Task_CurrentId() -> int {
return bux_task_current_id();
}
func Task_CurrentId() -> int {
return bux_task_current_id();
}
func Task_Shutdown() {
bux_task_shutdown();
}
func Task_Shutdown() {
bux_task_shutdown();
}
}
+75 -65
View File
@@ -1,76 +1,86 @@
module Std::Test {
import Std::Io::{PrintLine, PrintInt};
import Std::String::{String_Eq};
import Std::Io::{PrintLine, PrintInt};
import Std::String::{String_Eq};
extern func bux_exit(code: int);
extern func bux_assert(cond: int, file: String, line: int, expr: String);
extern func bux_exit(code: int);
extern func bux_assert(cond: int, file: String, line: int, expr: String);
func Test_Exit(code: int) {
bux_exit(code);
}
/// Exit the process with `code` (for test runners).
func Test_Exit(code: int) {
bux_exit(code);
}
func Test_Assert(cond: bool) {
bux_assert(cond as int, "", 0, "");
}
/// Assert `cond` is true; abort on failure.
func Test_Assert(cond: bool) {
bux_assert(cond as int, "", 0, "");
}
func Test_AssertEqInt(a: int, b: int) {
if a != b {
PrintLine("ASSERT_EQ_INT FAILED:");
PrintInt(a);
PrintLine(" != ");
PrintInt(b);
/// Assert two ints are equal; print both values and exit 1 on mismatch.
func Test_AssertEqInt(a: int, b: int) {
if a != b {
PrintLine("ASSERT_EQ_INT FAILED:");
PrintInt(a);
PrintLine(" != ");
PrintInt(b);
bux_exit(1);
}
}
/// Assert two ints differ.
func Test_AssertNeqInt(a: int, b: int) {
if a == b {
PrintLine("ASSERT_NEQ_INT FAILED: both are");
PrintInt(a);
bux_exit(1);
}
}
/// Assert two strings are equal (`String_Eq`).
func Test_AssertEqString(a: String, b: String) {
if !String_Eq(a, b) {
PrintLine("ASSERT_EQ_STRING FAILED:");
PrintLine(a);
PrintLine(" != ");
PrintLine(b);
bux_exit(1);
}
}
/// Assert two bools are equal.
func Test_AssertEqBool(a: bool, b: bool) {
if a != b {
PrintLine("ASSERT_EQ_BOOL FAILED");
bux_exit(1);
}
}
/// Assert `cond` is true.
func Test_AssertTrue(cond: bool) {
if !cond {
PrintLine("ASSERT_TRUE FAILED");
bux_exit(1);
}
}
/// Assert `cond` is false.
func Test_AssertFalse(cond: bool) {
if cond {
PrintLine("ASSERT_FALSE FAILED");
bux_exit(1);
}
}
/// Fail the test with a message and exit 1.
func Test_Fail(msg: String) {
PrintLine("FAIL:");
PrintLine(msg);
bux_exit(1);
}
}
func Test_AssertNeqInt(a: int, b: int) {
if a == b {
PrintLine("ASSERT_NEQ_INT FAILED: both are");
PrintInt(a);
bux_exit(1);
/// Print a PASS line (for human-readable runners / goldens).
func Test_Pass(msg: String) {
PrintLine("PASS:");
PrintLine(msg);
}
}
func Test_AssertEqString(a: String, b: String) {
if !String_Eq(a, b) {
PrintLine("ASSERT_EQ_STRING FAILED:");
PrintLine(a);
PrintLine(" != ");
PrintLine(b);
bux_exit(1);
}
}
func Test_AssertEqBool(a: bool, b: bool) {
if a != b {
PrintLine("ASSERT_EQ_BOOL FAILED");
bux_exit(1);
}
}
func Test_AssertTrue(cond: bool) {
if !cond {
PrintLine("ASSERT_TRUE FAILED");
bux_exit(1);
}
}
func Test_AssertFalse(cond: bool) {
if cond {
PrintLine("ASSERT_FALSE FAILED");
bux_exit(1);
}
}
func Test_Fail(msg: String) {
PrintLine("FAIL:");
PrintLine(msg);
bux_exit(1);
}
func Test_Pass(msg: String) {
PrintLine("PASS:");
PrintLine(msg);
}
}
+12 -12
View File
@@ -1,19 +1,19 @@
module Std::Time {
extern func bux_time_ms() -> int64;
extern func bux_time_us() -> int64;
extern func bux_sleep_ms(ms: int64);
extern func bux_time_ms() -> int64;
extern func bux_time_us() -> int64;
extern func bux_sleep_ms(ms: int64);
func Time_NowMs() -> int64 {
return bux_time_ms();
}
func Time_NowMs() -> int64 {
return bux_time_ms();
}
func Time_NowUs() -> int64 {
return bux_time_us();
}
func Time_NowUs() -> int64 {
return bux_time_us();
}
func Time_SleepMs(ms: int64) {
bux_sleep_ms(ms);
}
func Time_SleepMs(ms: int64) {
bux_sleep_ms(ms);
}
}
+49 -49
View File
@@ -3,65 +3,65 @@
// =============================================================================
module Std::Crypto::Aes {
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len};
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len};
extern func bux_random_bytes(buf: *void, len: int) -> int;
extern func bux_aes_256_cbc_encrypt(plain: String, plainlen: int, key: String, iv: String, outlen: *int) -> String;
extern func bux_aes_256_cbc_decrypt(cipher: String, cipherlen: int, key: String, iv: String, outlen: *int) -> String;
extern func bux_aes_256_gcm_encrypt(plain: String, plainlen: int, key: String, iv: String, tag: *void, outlen: *int) -> String;
extern func bux_aes_256_gcm_decrypt(cipher: String, cipherlen: int, key: String, iv: String, tag: String, outlen: *int) -> String;
extern func bux_random_bytes(buf: *void, len: int) -> int;
extern func bux_aes_256_cbc_encrypt(plain: String, plainlen: int, key: String, iv: String, outlen: *int) -> String;
extern func bux_aes_256_cbc_decrypt(cipher: String, cipherlen: int, key: String, iv: String, outlen: *int) -> String;
extern func bux_aes_256_gcm_encrypt(plain: String, plainlen: int, key: String, iv: String, tag: *void, outlen: *int) -> String;
extern func bux_aes_256_gcm_decrypt(cipher: String, cipherlen: int, key: String, iv: String, tag: String, outlen: *int) -> String;
// --- AES-256-CBC ---
// --- AES-256-CBC ---
const AES_KEY_SIZE: int = 32; // 256 bits
const AES_IV_SIZE: int = 16; // 128 bits
const AES_GCM_TAG_SIZE: int = 16;
const AES_KEY_SIZE: int = 32; // 256 bits
const AES_IV_SIZE: int = 16; // 128 bits
const AES_GCM_TAG_SIZE: int = 16;
// Generate a random 256-bit AES key (returns raw 32 bytes)
func Aes_GenerateKey() -> String {
let buf: *void = Alloc(AES_KEY_SIZE as uint);
if bux_random_bytes(buf, AES_KEY_SIZE) != 1 {
Free(buf);
return "";
// Generate a random 256-bit AES key (returns raw 32 bytes)
func Aes_GenerateKey() -> String {
let buf: *void = Alloc(AES_KEY_SIZE as uint);
if bux_random_bytes(buf, AES_KEY_SIZE) != 1 {
Free(buf);
return "";
}
return buf as String;
}
return buf as String;
}
// Generate a random 128-bit IV (returns raw 16 bytes)
func Aes_GenerateIV() -> String {
let buf: *void = Alloc(AES_IV_SIZE as uint);
if bux_random_bytes(buf, AES_IV_SIZE) != 1 {
Free(buf);
return "";
// Generate a random 128-bit IV (returns raw 16 bytes)
func Aes_GenerateIV() -> String {
let buf: *void = Alloc(AES_IV_SIZE as uint);
if bux_random_bytes(buf, AES_IV_SIZE) != 1 {
Free(buf);
return "";
}
return buf as String;
}
return buf as String;
}
// AES-256-CBC encrypt. plain and key are binary strings, iv is 16 bytes.
// Returns ciphertext (may be longer than plain due to PKCS#7 padding).
func Aes_CbcEncrypt(plain: String, key: String, iv: String) -> String {
let outlen: int = 0;
return bux_aes_256_cbc_encrypt(plain, String_Len(plain) as int, key, iv, &outlen);
}
// AES-256-CBC encrypt. plain and key are binary strings, iv is 16 bytes.
// Returns ciphertext (may be longer than plain due to PKCS#7 padding).
func Aes_CbcEncrypt(plain: String, key: String, iv: String) -> String {
let outlen: int = 0;
return bux_aes_256_cbc_encrypt(plain, String_Len(plain) as int, key, iv, &outlen);
}
// AES-256-CBC decrypt. Returns plaintext.
func Aes_CbcDecrypt(cipher: String, key: String, iv: String) -> String {
let outlen: int = 0;
return bux_aes_256_cbc_decrypt(cipher, String_Len(cipher) as int, key, iv, &outlen);
}
// AES-256-CBC decrypt. Returns plaintext.
func Aes_CbcDecrypt(cipher: String, key: String, iv: String) -> String {
let outlen: int = 0;
return bux_aes_256_cbc_decrypt(cipher, String_Len(cipher) as int, key, iv, &outlen);
}
// --- AES-256-GCM (Authenticated Encryption) ---
// --- AES-256-GCM (Authenticated Encryption) ---
// AES-256-GCM encrypt. Returns ciphertext. tag receives 16-byte authentication tag.
func Aes_GcmEncrypt(plain: String, key: String, iv: String, tag: *void) -> String {
let outlen: int = 0;
return bux_aes_256_gcm_encrypt(plain, String_Len(plain) as int, key, iv, tag, &outlen);
}
// AES-256-GCM encrypt. Returns ciphertext. tag receives 16-byte authentication tag.
func Aes_GcmEncrypt(plain: String, key: String, iv: String, tag: *void) -> String {
let outlen: int = 0;
return bux_aes_256_gcm_encrypt(plain, String_Len(plain) as int, key, iv, tag, &outlen);
}
// AES-256-GCM decrypt. Returns plaintext. tag must be the 16-byte auth tag from encryption.
func Aes_GcmDecrypt(cipher: String, key: String, iv: String, tag: String) -> String {
let outlen: int = 0;
return bux_aes_256_gcm_decrypt(cipher, String_Len(cipher) as int, key, iv, tag, &outlen);
}
// AES-256-GCM decrypt. Returns plaintext. tag must be the 16-byte auth tag from encryption.
func Aes_GcmDecrypt(cipher: String, key: String, iv: String, tag: String) -> String {
let outlen: int = 0;
return bux_aes_256_gcm_decrypt(cipher, String_Len(cipher) as int, key, iv, tag, &outlen);
}
}
+25 -25
View File
@@ -3,32 +3,32 @@
// =============================================================================
module Std::Crypto::Base64 {
import Std::String::{String_Len};
import Std::String::{String_Len};
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_base64_decode(data: String, len: int, outlen: *int) -> String;
extern func bux_base64url_encode(data: String, len: int) -> String;
extern func bux_base64url_decode(data: String, len: int, outlen: *int) -> String;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_base64_decode(data: String, len: int, outlen: *int) -> String;
extern func bux_base64url_encode(data: String, len: int) -> String;
extern func bux_base64url_decode(data: String, len: int, outlen: *int) -> String;
// --- Standard Base64 ---
// --- Standard Base64 ---
func Base64_Encode(s: String) -> String {
return bux_base64_encode(s, String_Len(s) as int);
}
func Base64_Decode(s: String) -> String {
let outlen: int = 0;
return bux_base64_decode(s, String_Len(s) as int, &outlen);
}
// --- Base64URL (RFC 4648 §5, uses - and _ instead of + and /, no padding) ---
func Base64URL_Encode(s: String) -> String {
return bux_base64url_encode(s, String_Len(s) as int);
}
func Base64URL_Decode(s: String) -> String {
let outlen: int = 0;
return bux_base64url_decode(s, String_Len(s) as int, &outlen);
}
func Base64_Encode(s: String) -> String {
return bux_base64_encode(s, String_Len(s) as int);
}
func Base64_Decode(s: String) -> String {
let outlen: int = 0;
return bux_base64_decode(s, String_Len(s) as int, &outlen);
}
// --- Base64URL (RFC 4648 §5, uses - and _ instead of + and /, no padding) ---
func Base64URL_Encode(s: String) -> String {
return bux_base64url_encode(s, String_Len(s) as int);
}
func Base64URL_Decode(s: String) -> String {
let outlen: int = 0;
return bux_base64url_decode(s, String_Len(s) as int, &outlen);
}
}
+43 -43
View File
@@ -3,56 +3,56 @@
// =============================================================================
module Std::Crypto::Ecdsa {
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len};
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len};
// Extern declarations for the runtime C implementations
extern func bux_ecdsa_sign_p256(key: String, keylen: int, data: String, datalen: int, outlen: *int) -> String;
extern func bux_ecdsa_verify_p256(key: String, keylen: int, data: String, datalen: int, sig: String, siglen: int) -> int;
extern func bux_ecdsa_sign_p384(key: String, keylen: int, data: String, datalen: int, outlen: *int) -> String;
extern func bux_ecdsa_verify_p384(key: String, keylen: int, data: String, datalen: int, sig: String, siglen: int) -> int;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_base64_decode(data: String, len: int, outlen: *int) -> String;
// Extern declarations for the runtime C implementations
extern func bux_ecdsa_sign_p256(key: String, keylen: int, data: String, datalen: int, outlen: *int) -> String;
extern func bux_ecdsa_verify_p256(key: String, keylen: int, data: String, datalen: int, sig: String, siglen: int) -> int;
extern func bux_ecdsa_sign_p384(key: String, keylen: int, data: String, datalen: int, outlen: *int) -> String;
extern func bux_ecdsa_verify_p384(key: String, keylen: int, data: String, datalen: int, sig: String, siglen: int) -> int;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_base64_decode(data: String, len: int, outlen: *int) -> String;
func Ecdsa_SignP256(pemPrivateKey: String, data: String) -> String {
let siglen: int = 0;
return bux_ecdsa_sign_p256(pemPrivateKey, String_Len(pemPrivateKey) as int, data, String_Len(data) as int, &siglen);
}
func Ecdsa_SignP256(pemPrivateKey: String, data: String) -> String {
let siglen: int = 0;
return bux_ecdsa_sign_p256(pemPrivateKey, String_Len(pemPrivateKey) as int, data, String_Len(data) as int, &siglen);
}
func Ecdsa_SignP256Base64(pemPrivateKey: String, data: String) -> String {
let raw: String = Ecdsa_SignP256(pemPrivateKey, data);
return bux_base64_encode(raw, String_Len(raw) as int);
}
func Ecdsa_SignP256Base64(pemPrivateKey: String, data: String) -> String {
let raw: String = Ecdsa_SignP256(pemPrivateKey, data);
return bux_base64_encode(raw, String_Len(raw) as int);
}
func Ecdsa_VerifyP256(pemPublicKey: String, data: String, signature: String) -> bool {
let r: int = bux_ecdsa_verify_p256(pemPublicKey, String_Len(pemPublicKey) as int, data, String_Len(data) as int, signature, String_Len(signature) as int);
return r == 1;
}
func Ecdsa_VerifyP256(pemPublicKey: String, data: String, signature: String) -> bool {
let r: int = bux_ecdsa_verify_p256(pemPublicKey, String_Len(pemPublicKey) as int, data, String_Len(data) as int, signature, String_Len(signature) as int);
return r == 1;
}
func Ecdsa_VerifyP256Base64(pemPublicKey: String, data: String, signatureB64: String) -> bool {
let outlen: int = 0;
let sig: String = bux_base64_decode(signatureB64, String_Len(signatureB64) as int, &outlen);
return Ecdsa_VerifyP256(pemPublicKey, data, sig);
}
func Ecdsa_VerifyP256Base64(pemPublicKey: String, data: String, signatureB64: String) -> bool {
let outlen: int = 0;
let sig: String = bux_base64_decode(signatureB64, String_Len(signatureB64) as int, &outlen);
return Ecdsa_VerifyP256(pemPublicKey, data, sig);
}
func Ecdsa_SignP384(pemPrivateKey: String, data: String) -> String {
let siglen: int = 0;
return bux_ecdsa_sign_p384(pemPrivateKey, String_Len(pemPrivateKey) as int, data, String_Len(data) as int, &siglen);
}
func Ecdsa_SignP384(pemPrivateKey: String, data: String) -> String {
let siglen: int = 0;
return bux_ecdsa_sign_p384(pemPrivateKey, String_Len(pemPrivateKey) as int, data, String_Len(data) as int, &siglen);
}
func Ecdsa_SignP384Base64(pemPrivateKey: String, data: String) -> String {
let raw: String = Ecdsa_SignP384(pemPrivateKey, data);
return bux_base64_encode(raw, String_Len(raw) as int);
}
func Ecdsa_SignP384Base64(pemPrivateKey: String, data: String) -> String {
let raw: String = Ecdsa_SignP384(pemPrivateKey, data);
return bux_base64_encode(raw, String_Len(raw) as int);
}
func Ecdsa_VerifyP384(pemPublicKey: String, data: String, signature: String) -> bool {
let r: int = bux_ecdsa_verify_p384(pemPublicKey, String_Len(pemPublicKey) as int, data, String_Len(data) as int, signature, String_Len(signature) as int);
return r == 1;
}
func Ecdsa_VerifyP384(pemPublicKey: String, data: String, signature: String) -> bool {
let r: int = bux_ecdsa_verify_p384(pemPublicKey, String_Len(pemPublicKey) as int, data, String_Len(data) as int, signature, String_Len(signature) as int);
return r == 1;
}
func Ecdsa_VerifyP384Base64(pemPublicKey: String, data: String, signatureB64: String) -> bool {
let outlen: int = 0;
let sig: String = bux_base64_decode(signatureB64, String_Len(signatureB64) as int, &outlen);
return Ecdsa_VerifyP384(pemPublicKey, data, sig);
}
func Ecdsa_VerifyP384Base64(pemPublicKey: String, data: String, signatureB64: String) -> bool {
let outlen: int = 0;
let sig: String = bux_base64_decode(signatureB64, String_Len(signatureB64) as int, &outlen);
return Ecdsa_VerifyP384(pemPublicKey, data, sig);
}
}
+59 -59
View File
@@ -3,78 +3,78 @@
// =============================================================================
module Std::Crypto::Ed25519 {
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len, String_Concat};
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len, String_Concat};
extern func bux_ed25519_keypair(pubKey: *void, privKey: *void) -> int;
extern func bux_ed25519_sign(privKey: String, data: String, datalen: int, sig: *void) -> int;
extern func bux_ed25519_verify(pubKey: String, sig: String, data: String, datalen: int) -> int;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_base64_decode(data: String, len: int, outlen: *int) -> String;
extern func bux_ed25519_keypair(pubKey: *void, privKey: *void) -> int;
extern func bux_ed25519_sign(privKey: String, data: String, datalen: int, sig: *void) -> int;
extern func bux_ed25519_verify(pubKey: String, sig: String, data: String, datalen: int) -> int;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_base64_decode(data: String, len: int, outlen: *int) -> String;
const ED25519_PUBKEY_SIZE: int = 32;
const ED25519_PRIVKEY_SIZE: int = 32;
const ED25519_SIG_SIZE: int = 64;
const ED25519_PUBKEY_SIZE: int = 32;
const ED25519_PRIVKEY_SIZE: int = 32;
const ED25519_SIG_SIZE: int = 64;
// --- Key Generation ---
// --- Key Generation ---
// Ed25519_Keypair: generates a new keypair.
// Returns true on success. pubKey and privKey receive 32-byte raw keys.
func Ed25519_Keypair(pubKey: *void, privKey: *void) -> bool {
let r: int = bux_ed25519_keypair(pubKey, privKey);
return r == 1;
}
// Ed25519_Keypair: generates a new keypair.
// Returns true on success. pubKey and privKey receive 32-byte raw keys.
func Ed25519_Keypair(pubKey: *void, privKey: *void) -> bool {
let r: int = bux_ed25519_keypair(pubKey, privKey);
return r == 1;
}
// Convenience: generate and return base64-encoded keypair
func Ed25519_KeypairBase64() -> String {
let pubBuf: *void = Alloc(ED25519_PUBKEY_SIZE as uint);
let priv: *void = Alloc(ED25519_PRIVKEY_SIZE as uint);
if bux_ed25519_keypair(pubBuf, priv) != 1 {
// Convenience: generate and return base64-encoded keypair
func Ed25519_KeypairBase64() -> String {
let pubBuf: *void = Alloc(ED25519_PUBKEY_SIZE as uint);
let priv: *void = Alloc(ED25519_PRIVKEY_SIZE as uint);
if bux_ed25519_keypair(pubBuf, priv) != 1 {
Free(pubBuf);
Free(priv);
return "";
}
// Return "pub_b64:priv_b64"
let pubB64: String = bux_base64_encode(pubBuf as String, ED25519_PUBKEY_SIZE);
let privB64: String = bux_base64_encode(priv as String, ED25519_PRIVKEY_SIZE);
Free(pubBuf);
Free(priv);
return "";
let pair: String = String_Concat(pubB64, ":");
return String_Concat(pair, privB64);
}
// Return "pub_b64:priv_b64"
let pubB64: String = bux_base64_encode(pubBuf as String, ED25519_PUBKEY_SIZE);
let privB64: String = bux_base64_encode(priv as String, ED25519_PRIVKEY_SIZE);
Free(pubBuf);
Free(priv);
let pair: String = String_Concat(pubB64, ":");
return String_Concat(pair, privB64);
}
// --- Sign ---
// --- Sign ---
// Ed25519_Sign: sign data with 32-byte raw private key. Returns 64-byte raw signature.
func Ed25519_Sign(privKey: String, data: String) -> String {
let sig: *void = Alloc(ED25519_SIG_SIZE as uint);
if bux_ed25519_sign(privKey, data, String_Len(data) as int, sig) != 1 {
Free(sig);
return "";
// Ed25519_Sign: sign data with 32-byte raw private key. Returns 64-byte raw signature.
func Ed25519_Sign(privKey: String, data: String) -> String {
let sig: *void = Alloc(ED25519_SIG_SIZE as uint);
if bux_ed25519_sign(privKey, data, String_Len(data) as int, sig) != 1 {
Free(sig);
return "";
}
return sig as String;
}
return sig as String;
}
// Convenience: sign and return base64-encoded signature
func Ed25519_SignBase64(privKey: String, data: String) -> String {
let sig: String = Ed25519_Sign(privKey, data);
if String_Len(sig) == 0 { return ""; }
return bux_base64_encode(sig, ED25519_SIG_SIZE);
}
// Convenience: sign and return base64-encoded signature
func Ed25519_SignBase64(privKey: String, data: String) -> String {
let sig: String = Ed25519_Sign(privKey, data);
if String_Len(sig) == 0 { return ""; }
return bux_base64_encode(sig, ED25519_SIG_SIZE);
}
// --- Verify ---
// --- Verify ---
// Ed25519_Verify: verify a 64-byte raw signature against data with 32-byte public key.
func Ed25519_Verify(pubKey: String, signature: String, data: String) -> bool {
let r: int = bux_ed25519_verify(pubKey, signature, data, String_Len(data) as int);
return r == 1;
}
// Ed25519_Verify: verify a 64-byte raw signature against data with 32-byte public key.
func Ed25519_Verify(pubKey: String, signature: String, data: String) -> bool {
let r: int = bux_ed25519_verify(pubKey, signature, data, String_Len(data) as int);
return r == 1;
}
// Convenience: verify a base64-encoded signature
func Ed25519_VerifyBase64(pubKey: String, signatureB64: String, data: String) -> bool {
let outlen: int = 0;
let sig: String = bux_base64_decode(signatureB64, String_Len(signatureB64) as int, &outlen);
if outlen != ED25519_SIG_SIZE { return false; }
return Ed25519_Verify(pubKey, sig, data);
}
// Convenience: verify a base64-encoded signature
func Ed25519_VerifyBase64(pubKey: String, signatureB64: String, data: String) -> bool {
let outlen: int = 0;
let sig: String = bux_base64_decode(signatureB64, String_Len(signatureB64) as int, &outlen);
if outlen != ED25519_SIG_SIZE { return false; }
return Ed25519_Verify(pubKey, sig, data);
}
}
+64 -64
View File
@@ -3,71 +3,71 @@
// =============================================================================
module Std::Crypto::Hash {
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len};
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len};
extern func bux_sha1(data: String, len: int, out: *void);
extern func bux_sha256(data: String, len: int, out: *void);
extern func bux_sha384(data: String, len: int, out: *void);
extern func bux_sha512(data: String, len: int, out: *void);
extern func bux_bytes_to_hex(data: *void, len: int) -> String;
extern func bux_sha1(data: String, len: int, out: *void);
extern func bux_sha256(data: String, len: int, out: *void);
extern func bux_sha384(data: String, len: int, out: *void);
extern func bux_sha512(data: String, len: int, out: *void);
extern func bux_bytes_to_hex(data: *void, len: int) -> String;
// --- Convenience wrappers: hex output ---
// --- Convenience wrappers: hex output ---
func Hash_Sha1(data: String) -> String {
let len: int = String_Len(data) as int;
let buf: *void = Alloc(20);
bux_sha1(data, len, buf);
let result: String = bux_bytes_to_hex(buf, 20);
Free(buf);
return result;
}
func Hash_Sha256(data: String) -> String {
let len: int = String_Len(data) as int;
let buf: *void = Alloc(32);
bux_sha256(data, len, buf);
let result: String = bux_bytes_to_hex(buf, 32);
Free(buf);
return result;
}
func Hash_Sha384(data: String) -> String {
let len: int = String_Len(data) as int;
let buf: *void = Alloc(48);
bux_sha384(data, len, buf);
let result: String = bux_bytes_to_hex(buf, 48);
Free(buf);
return result;
}
func Hash_Sha512(data: String) -> String {
let len: int = String_Len(data) as int;
let buf: *void = Alloc(64);
bux_sha512(data, len, buf);
let result: String = bux_bytes_to_hex(buf, 64);
Free(buf);
return result;
}
// --- Raw binary output (caller must Alloc/Free) ---
func Hash_Sha256Raw(data: String, out: *void) {
bux_sha256(data, String_Len(data) as int, out);
}
func Hash_Sha384Raw(data: String, out: *void) {
bux_sha384(data, String_Len(data) as int, out);
}
func Hash_Sha512Raw(data: String, out: *void) {
bux_sha512(data, String_Len(data) as int, out);
}
// --- Digest sizes ---
func Hash_Sha1Size() -> int { return 20; }
func Hash_Sha256Size() -> int { return 32; }
func Hash_Sha384Size() -> int { return 48; }
func Hash_Sha512Size() -> int { return 64; }
func Hash_Sha1(data: String) -> String {
let len: int = String_Len(data) as int;
let buf: *void = Alloc(20);
bux_sha1(data, len, buf);
let result: String = bux_bytes_to_hex(buf, 20);
Free(buf);
return result;
}
func Hash_Sha256(data: String) -> String {
let len: int = String_Len(data) as int;
let buf: *void = Alloc(32);
bux_sha256(data, len, buf);
let result: String = bux_bytes_to_hex(buf, 32);
Free(buf);
return result;
}
func Hash_Sha384(data: String) -> String {
let len: int = String_Len(data) as int;
let buf: *void = Alloc(48);
bux_sha384(data, len, buf);
let result: String = bux_bytes_to_hex(buf, 48);
Free(buf);
return result;
}
func Hash_Sha512(data: String) -> String {
let len: int = String_Len(data) as int;
let buf: *void = Alloc(64);
bux_sha512(data, len, buf);
let result: String = bux_bytes_to_hex(buf, 64);
Free(buf);
return result;
}
// --- Raw binary output (caller must Alloc/Free) ---
func Hash_Sha256Raw(data: String, out: *void) {
bux_sha256(data, String_Len(data) as int, out);
}
func Hash_Sha384Raw(data: String, out: *void) {
bux_sha384(data, String_Len(data) as int, out);
}
func Hash_Sha512Raw(data: String, out: *void) {
bux_sha512(data, String_Len(data) as int, out);
}
// --- Digest sizes ---
func Hash_Sha1Size() -> int { return 20; }
func Hash_Sha256Size() -> int { return 32; }
func Hash_Sha384Size() -> int { return 48; }
func Hash_Sha512Size() -> int { return 64; }
}
+83 -83
View File
@@ -3,90 +3,90 @@
// =============================================================================
module Std::Crypto::Hmac {
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len};
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len};
extern func bux_hmac_sha256(key: String, keylen: int, msg: String, msglen: int, out: *void);
extern func bux_hmac_sha384(key: String, keylen: int, msg: String, msglen: int, out: *void);
extern func bux_hmac_sha512(key: String, keylen: int, msg: String, msglen: int, out: *void);
extern func bux_bytes_to_hex(data: *void, len: int) -> String;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_hmac_sha256(key: String, keylen: int, msg: String, msglen: int, out: *void);
extern func bux_hmac_sha384(key: String, keylen: int, msg: String, msglen: int, out: *void);
extern func bux_hmac_sha512(key: String, keylen: int, msg: String, msglen: int, out: *void);
extern func bux_bytes_to_hex(data: *void, len: int) -> String;
extern func bux_base64_encode(data: String, len: int) -> String;
// --- HMAC-SHA256 ---
// --- HMAC-SHA256 ---
func Hmac_Sha256(key: String, message: String) -> String {
let kl: int = String_Len(key) as int;
let ml: int = String_Len(message) as int;
let buf: *void = Alloc(32);
bux_hmac_sha256(key, kl, message, ml, buf);
let result: String = bux_bytes_to_hex(buf, 32);
Free(buf);
return result;
}
func Hmac_Sha256Raw(key: String, message: String, out: *void) {
bux_hmac_sha256(key, String_Len(key) as int, message, String_Len(message) as int, out);
}
func Hmac_Sha256Base64(key: String, message: String) -> String {
let kl: int = String_Len(key) as int;
let ml: int = String_Len(message) as int;
let buf: *void = Alloc(32);
bux_hmac_sha256(key, kl, message, ml, buf);
let result: String = bux_base64_encode(buf as String, 32);
Free(buf);
return result;
}
// --- HMAC-SHA384 ---
func Hmac_Sha384(key: String, message: String) -> String {
let kl: int = String_Len(key) as int;
let ml: int = String_Len(message) as int;
let buf: *void = Alloc(48);
bux_hmac_sha384(key, kl, message, ml, buf);
let result: String = bux_bytes_to_hex(buf, 48);
Free(buf);
return result;
}
func Hmac_Sha384Raw(key: String, message: String, out: *void) {
bux_hmac_sha384(key, String_Len(key) as int, message, String_Len(message) as int, out);
}
func Hmac_Sha384Base64(key: String, message: String) -> String {
let kl: int = String_Len(key) as int;
let ml: int = String_Len(message) as int;
let buf: *void = Alloc(48);
bux_hmac_sha384(key, kl, message, ml, buf);
let result: String = bux_base64_encode(buf as String, 48);
Free(buf);
return result;
}
// --- HMAC-SHA512 ---
func Hmac_Sha512(key: String, message: String) -> String {
let kl: int = String_Len(key) as int;
let ml: int = String_Len(message) as int;
let buf: *void = Alloc(64);
bux_hmac_sha512(key, kl, message, ml, buf);
let result: String = bux_bytes_to_hex(buf, 64);
Free(buf);
return result;
}
func Hmac_Sha512Raw(key: String, message: String, out: *void) {
bux_hmac_sha512(key, String_Len(key) as int, message, String_Len(message) as int, out);
}
func Hmac_Sha512Base64(key: String, message: String) -> String {
let kl: int = String_Len(key) as int;
let ml: int = String_Len(message) as int;
let buf: *void = Alloc(64);
bux_hmac_sha512(key, kl, message, ml, buf);
let result: String = bux_base64_encode(buf as String, 64);
Free(buf);
return result;
}
func Hmac_Sha256(key: String, message: String) -> String {
let kl: int = String_Len(key) as int;
let ml: int = String_Len(message) as int;
let buf: *void = Alloc(32);
bux_hmac_sha256(key, kl, message, ml, buf);
let result: String = bux_bytes_to_hex(buf, 32);
Free(buf);
return result;
}
func Hmac_Sha256Raw(key: String, message: String, out: *void) {
bux_hmac_sha256(key, String_Len(key) as int, message, String_Len(message) as int, out);
}
func Hmac_Sha256Base64(key: String, message: String) -> String {
let kl: int = String_Len(key) as int;
let ml: int = String_Len(message) as int;
let buf: *void = Alloc(32);
bux_hmac_sha256(key, kl, message, ml, buf);
let result: String = bux_base64_encode(buf as String, 32);
Free(buf);
return result;
}
// --- HMAC-SHA384 ---
func Hmac_Sha384(key: String, message: String) -> String {
let kl: int = String_Len(key) as int;
let ml: int = String_Len(message) as int;
let buf: *void = Alloc(48);
bux_hmac_sha384(key, kl, message, ml, buf);
let result: String = bux_bytes_to_hex(buf, 48);
Free(buf);
return result;
}
func Hmac_Sha384Raw(key: String, message: String, out: *void) {
bux_hmac_sha384(key, String_Len(key) as int, message, String_Len(message) as int, out);
}
func Hmac_Sha384Base64(key: String, message: String) -> String {
let kl: int = String_Len(key) as int;
let ml: int = String_Len(message) as int;
let buf: *void = Alloc(48);
bux_hmac_sha384(key, kl, message, ml, buf);
let result: String = bux_base64_encode(buf as String, 48);
Free(buf);
return result;
}
// --- HMAC-SHA512 ---
func Hmac_Sha512(key: String, message: String) -> String {
let kl: int = String_Len(key) as int;
let ml: int = String_Len(message) as int;
let buf: *void = Alloc(64);
bux_hmac_sha512(key, kl, message, ml, buf);
let result: String = bux_bytes_to_hex(buf, 64);
Free(buf);
return result;
}
func Hmac_Sha512Raw(key: String, message: String, out: *void) {
bux_hmac_sha512(key, String_Len(key) as int, message, String_Len(message) as int, out);
}
func Hmac_Sha512Base64(key: String, message: String) -> String {
let kl: int = String_Len(key) as int;
let ml: int = String_Len(message) as int;
let buf: *void = Alloc(64);
bux_hmac_sha512(key, kl, message, ml, buf);
let result: String = bux_base64_encode(buf as String, 64);
Free(buf);
return result;
}
}
+206 -206
View File
@@ -4,233 +4,233 @@
// =============================================================================
module Std::Crypto::Jwt {
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len, String_Eq, String_StartsWith, String_Concat};
import Std::Crypto::Base64::{Base64URL_Encode, Base64URL_Decode};
import Std::Crypto::Hash::{Hash_Sha256Raw, Hash_Sha384Raw, Hash_Sha512Raw};
import Std::Crypto::Hmac::{Hmac_Sha256Raw, Hmac_Sha384Raw, Hmac_Sha512Raw};
import Std::Crypto::Rsa::{Rsa_SignSha256, Rsa_SignSha384, Rsa_SignSha512,
Rsa_VerifySha256, Rsa_VerifySha384, Rsa_VerifySha512};
import Std::Crypto::Ecdsa::{Ecdsa_SignP256, Ecdsa_SignP384, Ecdsa_VerifyP256, Ecdsa_VerifyP384};
import Std::Crypto::Ed25519::{Ed25519_Sign, Ed25519_Verify};
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len, String_Eq, String_StartsWith, String_Concat};
import Std::Crypto::Base64::{Base64URL_Encode, Base64URL_Decode};
import Std::Crypto::Hash::{Hash_Sha256Raw, Hash_Sha384Raw, Hash_Sha512Raw};
import Std::Crypto::Hmac::{Hmac_Sha256Raw, Hmac_Sha384Raw, Hmac_Sha512Raw};
import Std::Crypto::Rsa::{Rsa_SignSha256, Rsa_SignSha384, Rsa_SignSha512,
Rsa_VerifySha256, Rsa_VerifySha384, Rsa_VerifySha512};
import Std::Crypto::Ecdsa::{Ecdsa_SignP256, Ecdsa_SignP384, Ecdsa_VerifyP256, Ecdsa_VerifyP384};
import Std::Crypto::Ed25519::{Ed25519_Sign, Ed25519_Verify};
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_str_split_count(s: String, delim: String) -> uint;
extern func bux_str_split_part(s: String, delim: String, index: uint) -> String;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_str_split_count(s: String, delim: String) -> uint;
extern func bux_str_split_part(s: String, delim: String, index: uint) -> String;
// --- JWT Algorithm enum ---
enum JwtAlg {
HS256,
HS384,
HS512,
RS256,
RS384,
RS512,
ES256,
ES384,
EdDSA,
}
// --- Header ---
// Jwt_MakeHeader: build the JWT header JSON string for the given algorithm
func Jwt_MakeHeader(alg: JwtAlg) -> String {
if alg.tag == JwtAlg_HS256 { return "{\"alg\":\"HS256\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_HS384 { return "{\"alg\":\"HS384\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_HS512 { return "{\"alg\":\"HS512\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_RS256 { return "{\"alg\":\"RS256\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_RS384 { return "{\"alg\":\"RS384\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_RS512 { return "{\"alg\":\"RS512\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_ES256 { return "{\"alg\":\"ES256\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_ES384 { return "{\"alg\":\"ES384\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_EdDSA { return "{\"alg\":\"EdDSA\",\"typ\":\"JWT\"}"; }
return "{\"alg\":\"none\",\"typ\":\"JWT\"}";
}
// --- Signing ---
// Sign the JWT signing input with the given algorithm
func Jwt_Sign(alg: JwtAlg, signingInput: String, key: String) -> String {
// --- HMAC algorithms ---
if alg.tag == JwtAlg_HS256 {
let buf: *void = Alloc(32);
Hmac_Sha256Raw(key, signingInput, buf);
let result: String = bux_base64_encode(buf as String, 32);
Free(buf);
return result;
}
if alg.tag == JwtAlg_HS384 {
let buf: *void = Alloc(48);
Hmac_Sha384Raw(key, signingInput, buf);
let result: String = bux_base64_encode(buf as String, 48);
Free(buf);
return result;
}
if alg.tag == JwtAlg_HS512 {
let buf: *void = Alloc(64);
Hmac_Sha512Raw(key, signingInput, buf);
let result: String = bux_base64_encode(buf as String, 64);
Free(buf);
return result;
// --- JWT Algorithm enum ---
enum JwtAlg {
HS256,
HS384,
HS512,
RS256,
RS384,
RS512,
ES256,
ES384,
EdDSA,
}
// --- RSA algorithms (key is PEM private key) ---
if alg.tag == JwtAlg_RS256 {
let raw: String = Rsa_SignSha256(key, signingInput);
return bux_base64_encode(raw, String_Len(raw) as int);
}
if alg.tag == JwtAlg_RS384 {
let raw: String = Rsa_SignSha384(key, signingInput);
return bux_base64_encode(raw, String_Len(raw) as int);
}
if alg.tag == JwtAlg_RS512 {
let raw: String = Rsa_SignSha512(key, signingInput);
return bux_base64_encode(raw, String_Len(raw) as int);
// --- Header ---
// Jwt_MakeHeader: build the JWT header JSON string for the given algorithm
func Jwt_MakeHeader(alg: JwtAlg) -> String {
if alg.tag == JwtAlg_HS256 { return "{\"alg\":\"HS256\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_HS384 { return "{\"alg\":\"HS384\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_HS512 { return "{\"alg\":\"HS512\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_RS256 { return "{\"alg\":\"RS256\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_RS384 { return "{\"alg\":\"RS384\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_RS512 { return "{\"alg\":\"RS512\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_ES256 { return "{\"alg\":\"ES256\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_ES384 { return "{\"alg\":\"ES384\",\"typ\":\"JWT\"}"; }
if alg.tag == JwtAlg_EdDSA { return "{\"alg\":\"EdDSA\",\"typ\":\"JWT\"}"; }
return "{\"alg\":\"none\",\"typ\":\"JWT\"}";
}
// --- ECDSA algorithms (key is PEM private key) ---
if alg.tag == JwtAlg_ES256 {
let raw: String = Ecdsa_SignP256(key, signingInput);
return bux_base64_encode(raw, String_Len(raw) as int);
}
if alg.tag == JwtAlg_ES384 {
let raw: String = Ecdsa_SignP384(key, signingInput);
return bux_base64_encode(raw, String_Len(raw) as int);
// --- Signing ---
// Sign the JWT signing input with the given algorithm
func Jwt_Sign(alg: JwtAlg, signingInput: String, key: String) -> String {
// --- HMAC algorithms ---
if alg.tag == JwtAlg_HS256 {
let buf: *void = Alloc(32);
Hmac_Sha256Raw(key, signingInput, buf);
let result: String = bux_base64_encode(buf as String, 32);
Free(buf);
return result;
}
if alg.tag == JwtAlg_HS384 {
let buf: *void = Alloc(48);
Hmac_Sha384Raw(key, signingInput, buf);
let result: String = bux_base64_encode(buf as String, 48);
Free(buf);
return result;
}
if alg.tag == JwtAlg_HS512 {
let buf: *void = Alloc(64);
Hmac_Sha512Raw(key, signingInput, buf);
let result: String = bux_base64_encode(buf as String, 64);
Free(buf);
return result;
}
// --- RSA algorithms (key is PEM private key) ---
if alg.tag == JwtAlg_RS256 {
let raw: String = Rsa_SignSha256(key, signingInput);
return bux_base64_encode(raw, String_Len(raw) as int);
}
if alg.tag == JwtAlg_RS384 {
let raw: String = Rsa_SignSha384(key, signingInput);
return bux_base64_encode(raw, String_Len(raw) as int);
}
if alg.tag == JwtAlg_RS512 {
let raw: String = Rsa_SignSha512(key, signingInput);
return bux_base64_encode(raw, String_Len(raw) as int);
}
// --- ECDSA algorithms (key is PEM private key) ---
if alg.tag == JwtAlg_ES256 {
let raw: String = Ecdsa_SignP256(key, signingInput);
return bux_base64_encode(raw, String_Len(raw) as int);
}
if alg.tag == JwtAlg_ES384 {
let raw: String = Ecdsa_SignP384(key, signingInput);
return bux_base64_encode(raw, String_Len(raw) as int);
}
// --- EdDSA (key is 32-byte raw private key) ---
if alg.tag == JwtAlg_EdDSA {
return Ed25519_Sign(key, signingInput);
}
return "";
}
// --- EdDSA (key is 32-byte raw private key) ---
if alg.tag == JwtAlg_EdDSA {
return Ed25519_Sign(key, signingInput);
}
// --- Verify ---
return "";
}
// Verify a JWT signature
func Jwt_Verify(alg: JwtAlg, signingInput: String, signatureB64: String, key: String) -> bool {
// --- HMAC algorithms ---
if alg.tag == JwtAlg_HS256 {
let expectBuf: *void = Alloc(32);
Hmac_Sha256Raw(key, signingInput, expectBuf);
let expectB64: String = bux_base64_encode(expectBuf as String, 32);
Free(expectBuf);
return String_Eq(expectB64, signatureB64);
}
if alg.tag == JwtAlg_HS384 {
let expectBuf: *void = Alloc(48);
Hmac_Sha384Raw(key, signingInput, expectBuf);
let expectB64: String = bux_base64_encode(expectBuf as String, 48);
Free(expectBuf);
return String_Eq(expectB64, signatureB64);
}
if alg.tag == JwtAlg_HS512 {
let expectBuf: *void = Alloc(64);
Hmac_Sha512Raw(key, signingInput, expectBuf);
let expectB64: String = bux_base64_encode(expectBuf as String, 64);
Free(expectBuf);
return String_Eq(expectB64, signatureB64);
}
// --- Verify ---
// --- RSA algorithms ---
if alg.tag == JwtAlg_RS256 { return Rsa_VerifySha256(key, signingInput, signatureB64); }
if alg.tag == JwtAlg_RS384 { return Rsa_VerifySha384(key, signingInput, signatureB64); }
if alg.tag == JwtAlg_RS512 { return Rsa_VerifySha512(key, signingInput, signatureB64); }
// Verify a JWT signature
func Jwt_Verify(alg: JwtAlg, signingInput: String, signatureB64: String, key: String) -> bool {
// --- HMAC algorithms ---
if alg.tag == JwtAlg_HS256 {
let expectBuf: *void = Alloc(32);
Hmac_Sha256Raw(key, signingInput, expectBuf);
let expectB64: String = bux_base64_encode(expectBuf as String, 32);
Free(expectBuf);
return String_Eq(expectB64, signatureB64);
}
if alg.tag == JwtAlg_HS384 {
let expectBuf: *void = Alloc(48);
Hmac_Sha384Raw(key, signingInput, expectBuf);
let expectB64: String = bux_base64_encode(expectBuf as String, 48);
Free(expectBuf);
return String_Eq(expectB64, signatureB64);
}
if alg.tag == JwtAlg_HS512 {
let expectBuf: *void = Alloc(64);
Hmac_Sha512Raw(key, signingInput, expectBuf);
let expectB64: String = bux_base64_encode(expectBuf as String, 64);
Free(expectBuf);
return String_Eq(expectB64, signatureB64);
}
// --- ECDSA algorithms ---
if alg.tag == JwtAlg_ES256 { return Ecdsa_VerifyP256(key, signingInput, signatureB64); }
if alg.tag == JwtAlg_ES384 { return Ecdsa_VerifyP384(key, signingInput, signatureB64); }
// --- RSA algorithms ---
if alg.tag == JwtAlg_RS256 { return Rsa_VerifySha256(key, signingInput, signatureB64); }
if alg.tag == JwtAlg_RS384 { return Rsa_VerifySha384(key, signingInput, signatureB64); }
if alg.tag == JwtAlg_RS512 { return Rsa_VerifySha512(key, signingInput, signatureB64); }
// --- EdDSA ---
if alg.tag == JwtAlg_EdDSA { return Ed25519_Verify(key, signatureB64, signingInput); }
// --- ECDSA algorithms ---
if alg.tag == JwtAlg_ES256 { return Ecdsa_VerifyP256(key, signingInput, signatureB64); }
if alg.tag == JwtAlg_ES384 { return Ecdsa_VerifyP384(key, signingInput, signatureB64); }
// --- EdDSA ---
if alg.tag == JwtAlg_EdDSA { return Ed25519_Verify(key, signatureB64, signingInput); }
return false;
}
// --- Encode ---
// Jwt_Encode: create a signed JWT
// headerJson — JSON header string (use Jwt_MakeHeader or custom)
// payloadJson — JSON payload/claims string
// alg — signing algorithm
// key — signing key (HMAC secret, RSA PEM, ECDSA PEM, or Ed25519 raw privkey)
// Returns the complete "header.payload.signature" JWT string
func Jwt_Encode(headerJson: String, payloadJson: String, alg: JwtAlg, key: String) -> String {
let headerB64: String = Base64URL_Encode(headerJson);
let payloadB64: String = Base64URL_Encode(payloadJson);
let signingInput: String = String_Concat(headerB64, ".");
let signingInputFull: String = String_Concat(signingInput, payloadB64);
let sigB64: String = Jwt_Sign(alg, signingInputFull, key);
let part1: String = String_Concat(signingInputFull, ".");
return String_Concat(part1, sigB64);
}
// --- Decode ---
// Jwt_Decode: decode and verify a JWT.
// token — the full "header.payload.signature" string
// alg — expected algorithm
// key — verification key
// headerOut — receives decoded header JSON
// payloadOut — receives decoded payload JSON
// Returns true if signature is valid.
func Jwt_Decode(token: String, alg: JwtAlg, key: String,
headerOut: *String, payloadOut: *String) -> bool {
// Split by "."
let partCount: uint = bux_str_split_count(token, ".");
if partCount != 3 { return false; }
let headerB64: String = bux_str_split_part(token, ".", 0);
let payloadB64: String = bux_str_split_part(token, ".", 1);
let sigB64: String = bux_str_split_part(token, ".", 2);
// Build signing input
let input: String = String_Concat(headerB64, ".");
let signingInput: String = String_Concat(input, payloadB64);
// Verify signature
if !Jwt_Verify(alg, signingInput, sigB64, key) {
return false;
}
// Decode
headerOut[0] = Base64URL_Decode(headerB64);
payloadOut[0] = Base64URL_Decode(payloadB64);
return true;
}
// --- Encode ---
// --- Convenience: Encode with standard header ---
// Jwt_Encode: create a signed JWT
// headerJson — JSON header string (use Jwt_MakeHeader or custom)
// payloadJson — JSON payload/claims string
// alg — signing algorithm
// key — signing key (HMAC secret, RSA PEM, ECDSA PEM, or Ed25519 raw privkey)
// Returns the complete "header.payload.signature" JWT string
func Jwt_Encode(headerJson: String, payloadJson: String, alg: JwtAlg, key: String) -> String {
let headerB64: String = Base64URL_Encode(headerJson);
let payloadB64: String = Base64URL_Encode(payloadJson);
let signingInput: String = String_Concat(headerB64, ".");
let signingInputFull: String = String_Concat(signingInput, payloadB64);
func Jwt_EncodeHS256(payloadJson: String, secret: String) -> String {
let header: String = Jwt_MakeHeader(JwtAlg { tag: JwtAlg_HS256 });
return Jwt_Encode(header, payloadJson, JwtAlg { tag: JwtAlg_HS256 }, secret);
}
let sigB64: String = Jwt_Sign(alg, signingInputFull, key);
func Jwt_EncodeHS384(payloadJson: String, secret: String) -> String {
let header: String = Jwt_MakeHeader(JwtAlg { tag: JwtAlg_HS384 });
return Jwt_Encode(header, payloadJson, JwtAlg { tag: JwtAlg_HS384 }, secret);
}
let part1: String = String_Concat(signingInputFull, ".");
return String_Concat(part1, sigB64);
}
func Jwt_EncodeHS512(payloadJson: String, secret: String) -> String {
let header: String = Jwt_MakeHeader(JwtAlg { tag: JwtAlg_HS512 });
return Jwt_Encode(header, payloadJson, JwtAlg { tag: JwtAlg_HS512 }, secret);
}
// --- Decode ---
func Jwt_EncodeRS256(payloadJson: String, pemPrivateKey: String) -> String {
let header: String = Jwt_MakeHeader(JwtAlg { tag: JwtAlg_RS256 });
return Jwt_Encode(header, payloadJson, JwtAlg { tag: JwtAlg_RS256 }, pemPrivateKey);
}
// Jwt_Decode: decode and verify a JWT.
// token — the full "header.payload.signature" string
// alg — expected algorithm
// key — verification key
// headerOut — receives decoded header JSON
// payloadOut — receives decoded payload JSON
// Returns true if signature is valid.
func Jwt_Decode(token: String, alg: JwtAlg, key: String,
headerOut: *String, payloadOut: *String) -> bool {
// Split by "."
let partCount: uint = bux_str_split_count(token, ".");
if partCount != 3 { return false; }
func Jwt_EncodeES256(payloadJson: String, pemPrivateKey: String) -> String {
let header: String = Jwt_MakeHeader(JwtAlg { tag: JwtAlg_ES256 });
return Jwt_Encode(header, payloadJson, JwtAlg { tag: JwtAlg_ES256 }, pemPrivateKey);
}
let headerB64: String = bux_str_split_part(token, ".", 0);
let payloadB64: String = bux_str_split_part(token, ".", 1);
let sigB64: String = bux_str_split_part(token, ".", 2);
func Jwt_EncodeEdDSA(payloadJson: String, rawPrivKey: String) -> String {
let header: String = Jwt_MakeHeader(JwtAlg { tag: JwtAlg_EdDSA });
return Jwt_Encode(header, payloadJson, JwtAlg { tag: JwtAlg_EdDSA }, rawPrivKey);
}
// Build signing input
let input: String = String_Concat(headerB64, ".");
let signingInput: String = String_Concat(input, payloadB64);
// Verify signature
if !Jwt_Verify(alg, signingInput, sigB64, key) {
return false;
}
// Decode
headerOut[0] = Base64URL_Decode(headerB64);
payloadOut[0] = Base64URL_Decode(payloadB64);
return true;
}
// --- Convenience: Encode with standard header ---
func Jwt_EncodeHS256(payloadJson: String, secret: String) -> String {
let header: String = Jwt_MakeHeader(JwtAlg { tag: JwtAlg_HS256 });
return Jwt_Encode(header, payloadJson, JwtAlg { tag: JwtAlg_HS256 }, secret);
}
func Jwt_EncodeHS384(payloadJson: String, secret: String) -> String {
let header: String = Jwt_MakeHeader(JwtAlg { tag: JwtAlg_HS384 });
return Jwt_Encode(header, payloadJson, JwtAlg { tag: JwtAlg_HS384 }, secret);
}
func Jwt_EncodeHS512(payloadJson: String, secret: String) -> String {
let header: String = Jwt_MakeHeader(JwtAlg { tag: JwtAlg_HS512 });
return Jwt_Encode(header, payloadJson, JwtAlg { tag: JwtAlg_HS512 }, secret);
}
func Jwt_EncodeRS256(payloadJson: String, pemPrivateKey: String) -> String {
let header: String = Jwt_MakeHeader(JwtAlg { tag: JwtAlg_RS256 });
return Jwt_Encode(header, payloadJson, JwtAlg { tag: JwtAlg_RS256 }, pemPrivateKey);
}
func Jwt_EncodeES256(payloadJson: String, pemPrivateKey: String) -> String {
let header: String = Jwt_MakeHeader(JwtAlg { tag: JwtAlg_ES256 });
return Jwt_Encode(header, payloadJson, JwtAlg { tag: JwtAlg_ES256 }, pemPrivateKey);
}
func Jwt_EncodeEdDSA(payloadJson: String, rawPrivKey: String) -> String {
let header: String = Jwt_MakeHeader(JwtAlg { tag: JwtAlg_EdDSA });
return Jwt_Encode(header, payloadJson, JwtAlg { tag: JwtAlg_EdDSA }, rawPrivKey);
}
}
+45 -45
View File
@@ -3,61 +3,61 @@
// =============================================================================
module Std::Crypto::Random {
import Std::Mem::{Alloc, Free};
import Std::Mem::{Alloc, Free};
extern func bux_random_bytes(buf: *void, len: int) -> int;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_bytes_to_hex(data: *void, len: int) -> String;
extern func bux_random_bytes(buf: *void, len: int) -> int;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_bytes_to_hex(data: *void, len: int) -> String;
// RandomBytes: returns n cryptographically secure random bytes as a raw string
func Random_Bytes(n: int) -> String {
if n <= 0 { return ""; }
let buf: *void = Alloc(n as uint);
if bux_random_bytes(buf, n) != 1 {
Free(buf);
return "";
// RandomBytes: returns n cryptographically secure random bytes as a raw string
func Random_Bytes(n: int) -> String {
if n <= 0 { return ""; }
let buf: *void = Alloc(n as uint);
if bux_random_bytes(buf, n) != 1 {
Free(buf);
return "";
}
// Return raw buffer as string (binary-safe)
return buf as String;
}
// Return raw buffer as string (binary-safe)
return buf as String;
}
// RandomHex: returns n random bytes as lowercase hex
func Random_Hex(n: int) -> String {
if n <= 0 { return ""; }
let buf: *void = Alloc(n as uint);
if bux_random_bytes(buf, n) != 1 {
// RandomHex: returns n random bytes as lowercase hex
func Random_Hex(n: int) -> String {
if n <= 0 { return ""; }
let buf: *void = Alloc(n as uint);
if bux_random_bytes(buf, n) != 1 {
Free(buf);
return "";
}
let result: String = bux_bytes_to_hex(buf, n);
Free(buf);
return "";
return result;
}
let result: String = bux_bytes_to_hex(buf, n);
Free(buf);
return result;
}
// RandomBase64: returns n random bytes as base64-encoded string
func Random_Base64(n: int) -> String {
if n <= 0 { return ""; }
let buf: *void = Alloc(n as uint);
if bux_random_bytes(buf, n) != 1 {
// RandomBase64: returns n random bytes as base64-encoded string
func Random_Base64(n: int) -> String {
if n <= 0 { return ""; }
let buf: *void = Alloc(n as uint);
if bux_random_bytes(buf, n) != 1 {
Free(buf);
return "";
}
let result: String = bux_base64_encode(buf as String, n);
Free(buf);
return "";
return result;
}
let result: String = bux_base64_encode(buf as String, n);
Free(buf);
return result;
}
// RandomUint32: returns a random 32-bit unsigned integer
func Random_Uint32() -> uint {
let buf: *void = Alloc(4);
if bux_random_bytes(buf, 4) != 1 {
// RandomUint32: returns a random 32-bit unsigned integer
func Random_Uint32() -> uint {
let buf: *void = Alloc(4);
if bux_random_bytes(buf, 4) != 1 {
Free(buf);
return 0;
}
// Interpret first 4 bytes as uint (native endian)
let ptr: *uint = buf as *uint;
let val: uint = *ptr;
Free(buf);
return 0;
return val;
}
// Interpret first 4 bytes as uint (native endian)
let ptr: *uint = buf as *uint;
let val: uint = *ptr;
Free(buf);
return val;
}
}
+81 -81
View File
@@ -3,88 +3,88 @@
// =============================================================================
module Std::Crypto::Rsa {
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len};
import Std::Mem::{Alloc, Free};
import Std::String::{String_Len};
// Extern declarations for the runtime C implementations
extern func bux_rsa_sign_sha256(key: String, keylen: int, data: String, datalen: int, outlen: *int) -> String;
extern func bux_rsa_sign_sha384(key: String, keylen: int, data: String, datalen: int, outlen: *int) -> String;
extern func bux_rsa_sign_sha512(key: String, keylen: int, data: String, datalen: int, outlen: *int) -> String;
extern func bux_rsa_verify_sha256(key: String, keylen: int, data: String, datalen: int, sig: String, siglen: int) -> int;
extern func bux_rsa_verify_sha384(key: String, keylen: int, data: String, datalen: int, sig: String, siglen: int) -> int;
extern func bux_rsa_verify_sha512(key: String, keylen: int, data: String, datalen: int, sig: String, siglen: int) -> int;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_base64_decode(data: String, len: int, outlen: *int) -> String;
// Extern declarations for the runtime C implementations
extern func bux_rsa_sign_sha256(key: String, keylen: int, data: String, datalen: int, outlen: *int) -> String;
extern func bux_rsa_sign_sha384(key: String, keylen: int, data: String, datalen: int, outlen: *int) -> String;
extern func bux_rsa_sign_sha512(key: String, keylen: int, data: String, datalen: int, outlen: *int) -> String;
extern func bux_rsa_verify_sha256(key: String, keylen: int, data: String, datalen: int, sig: String, siglen: int) -> int;
extern func bux_rsa_verify_sha384(key: String, keylen: int, data: String, datalen: int, sig: String, siglen: int) -> int;
extern func bux_rsa_verify_sha512(key: String, keylen: int, data: String, datalen: int, sig: String, siglen: int) -> int;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_base64_decode(data: String, len: int, outlen: *int) -> String;
// --- RSA Sign ---
// --- RSA Sign ---
// Rsa_SignSha256: sign data with RSA private key (PEM format), returns raw signature
func Rsa_SignSha256(pemPrivateKey: String, data: String) -> String {
let siglen: int = 0;
return bux_rsa_sign_sha256(pemPrivateKey, String_Len(pemPrivateKey) as int, data, String_Len(data) as int, &siglen);
}
func Rsa_SignSha384(pemPrivateKey: String, data: String) -> String {
let siglen: int = 0;
return bux_rsa_sign_sha384(pemPrivateKey, String_Len(pemPrivateKey) as int, data, String_Len(data) as int, &siglen);
}
func Rsa_SignSha512(pemPrivateKey: String, data: String) -> String {
let siglen: int = 0;
return bux_rsa_sign_sha512(pemPrivateKey, String_Len(pemPrivateKey) as int, data, String_Len(data) as int, &siglen);
}
// Convenience: sign and return base64-encoded signature
func Rsa_SignSha256Base64(pemPrivateKey: String, data: String) -> String {
let raw: String = Rsa_SignSha256(pemPrivateKey, data);
return bux_base64_encode(raw, String_Len(raw) as int);
}
func Rsa_SignSha384Base64(pemPrivateKey: String, data: String) -> String {
let raw: String = Rsa_SignSha384(pemPrivateKey, data);
return bux_base64_encode(raw, String_Len(raw) as int);
}
func Rsa_SignSha512Base64(pemPrivateKey: String, data: String) -> String {
let raw: String = Rsa_SignSha512(pemPrivateKey, data);
return bux_base64_encode(raw, String_Len(raw) as int);
}
// --- RSA Verify ---
// Rsa_VerifySha256: verify raw signature against data with RSA public key (PEM)
// Returns true if signature is valid.
func Rsa_VerifySha256(pemPublicKey: String, data: String, signature: String) -> bool {
let r: int = bux_rsa_verify_sha256(pemPublicKey, String_Len(pemPublicKey) as int, data, String_Len(data) as int, signature, String_Len(signature) as int);
return r == 1;
}
func Rsa_VerifySha384(pemPublicKey: String, data: String, signature: String) -> bool {
let r: int = bux_rsa_verify_sha384(pemPublicKey, String_Len(pemPublicKey) as int, data, String_Len(data) as int, signature, String_Len(signature) as int);
return r == 1;
}
func Rsa_VerifySha512(pemPublicKey: String, data: String, signature: String) -> bool {
let r: int = bux_rsa_verify_sha512(pemPublicKey, String_Len(pemPublicKey) as int, data, String_Len(data) as int, signature, String_Len(signature) as int);
return r == 1;
}
// Convenience: verify base64-encoded signature
func Rsa_VerifySha256Base64(pemPublicKey: String, data: String, signatureB64: String) -> bool {
let outlen: int = 0;
let sig: String = bux_base64_decode(signatureB64, String_Len(signatureB64) as int, &outlen);
return Rsa_VerifySha256(pemPublicKey, data, sig);
}
func Rsa_VerifySha384Base64(pemPublicKey: String, data: String, signatureB64: String) -> bool {
let outlen: int = 0;
let sig: String = bux_base64_decode(signatureB64, String_Len(signatureB64) as int, &outlen);
return Rsa_VerifySha384(pemPublicKey, data, sig);
}
func Rsa_VerifySha512Base64(pemPublicKey: String, data: String, signatureB64: String) -> bool {
let outlen: int = 0;
let sig: String = bux_base64_decode(signatureB64, String_Len(signatureB64) as int, &outlen);
return Rsa_VerifySha512(pemPublicKey, data, sig);
}
// Rsa_SignSha256: sign data with RSA private key (PEM format), returns raw signature
func Rsa_SignSha256(pemPrivateKey: String, data: String) -> String {
let siglen: int = 0;
return bux_rsa_sign_sha256(pemPrivateKey, String_Len(pemPrivateKey) as int, data, String_Len(data) as int, &siglen);
}
func Rsa_SignSha384(pemPrivateKey: String, data: String) -> String {
let siglen: int = 0;
return bux_rsa_sign_sha384(pemPrivateKey, String_Len(pemPrivateKey) as int, data, String_Len(data) as int, &siglen);
}
func Rsa_SignSha512(pemPrivateKey: String, data: String) -> String {
let siglen: int = 0;
return bux_rsa_sign_sha512(pemPrivateKey, String_Len(pemPrivateKey) as int, data, String_Len(data) as int, &siglen);
}
// Convenience: sign and return base64-encoded signature
func Rsa_SignSha256Base64(pemPrivateKey: String, data: String) -> String {
let raw: String = Rsa_SignSha256(pemPrivateKey, data);
return bux_base64_encode(raw, String_Len(raw) as int);
}
func Rsa_SignSha384Base64(pemPrivateKey: String, data: String) -> String {
let raw: String = Rsa_SignSha384(pemPrivateKey, data);
return bux_base64_encode(raw, String_Len(raw) as int);
}
func Rsa_SignSha512Base64(pemPrivateKey: String, data: String) -> String {
let raw: String = Rsa_SignSha512(pemPrivateKey, data);
return bux_base64_encode(raw, String_Len(raw) as int);
}
// --- RSA Verify ---
// Rsa_VerifySha256: verify raw signature against data with RSA public key (PEM)
// Returns true if signature is valid.
func Rsa_VerifySha256(pemPublicKey: String, data: String, signature: String) -> bool {
let r: int = bux_rsa_verify_sha256(pemPublicKey, String_Len(pemPublicKey) as int, data, String_Len(data) as int, signature, String_Len(signature) as int);
return r == 1;
}
func Rsa_VerifySha384(pemPublicKey: String, data: String, signature: String) -> bool {
let r: int = bux_rsa_verify_sha384(pemPublicKey, String_Len(pemPublicKey) as int, data, String_Len(data) as int, signature, String_Len(signature) as int);
return r == 1;
}
func Rsa_VerifySha512(pemPublicKey: String, data: String, signature: String) -> bool {
let r: int = bux_rsa_verify_sha512(pemPublicKey, String_Len(pemPublicKey) as int, data, String_Len(data) as int, signature, String_Len(signature) as int);
return r == 1;
}
// Convenience: verify base64-encoded signature
func Rsa_VerifySha256Base64(pemPublicKey: String, data: String, signatureB64: String) -> bool {
let outlen: int = 0;
let sig: String = bux_base64_decode(signatureB64, String_Len(signatureB64) as int, &outlen);
return Rsa_VerifySha256(pemPublicKey, data, sig);
}
func Rsa_VerifySha384Base64(pemPublicKey: String, data: String, signatureB64: String) -> bool {
let outlen: int = 0;
let sig: String = bux_base64_decode(signatureB64, String_Len(signatureB64) as int, &outlen);
return Rsa_VerifySha384(pemPublicKey, data, sig);
}
func Rsa_VerifySha512Base64(pemPublicKey: String, data: String, signatureB64: String) -> bool {
let outlen: int = 0;
let sig: String = bux_base64_decode(signatureB64, String_Len(signatureB64) as int, &outlen);
return Rsa_VerifySha512(pemPublicKey, data, sig);
}
}