Flash 168 lines
// cookbook — the COOKBOOK.md recipes as one compiled module.
//
// Every fenced Flash example in COOKBOOK.md lives here as real code, so a
// recipe can never drift into syntax the compiler rejects, and the test
// blocks run the recipes against the standard library for real.
//
// Lives in examples/register/ (post-v0.5 grammar — the frozen stage0
// bootstrap compiler cannot parse it; gated by `zig build fixpoint`).
use std
use core
const Allocator = std.mem.Allocator
// --- One arena per job ---
// Allocate freely inside the job, release everything with one deinit.
// Whatever must outlive the arena is copied out to the caller's allocator
// before the function returns.
pub fn greeting(child Allocator, name []u8, attempt u32) ![]u8 {
var arena = core.arena.ArenaAllocator.init(child)
defer arena.deinit()
alloc := arena.allocator()
line := try core.fmt.allocPrint(alloc, "hello {s}, attempt {d}", .{ name, attempt })
return child.dupe(u8, line)
}
// --- Error handling ---
pub const ConfigError = error{ NotFound, OutOfMemory }
// Originate with `error.Name`, propagate with `try`, recover with `catch`.
pub fn valueOf(table [][]u8, key []u8) ConfigError![]u8 {
for line in table {
if core.mem.indexOfScalar(u8, line, '=') |eq| {
if core.mem.eql(u8, line[0..eq], key) {
return line[eq + 1 ..]
}
}
}
return error.NotFound
}
pub fn portOrDefault(s []u8) u16 {
return core.fmt.parseInt(u16, s, 10) catch 8080
}
// errdefer releases what is already built when a later step fails.
pub fn dupePair(alloc Allocator, a []u8, b []u8) ![2][]u8 {
first := try alloc.dupe(u8, a)
errdefer alloc.free(first)
second := try alloc.dupe(u8, b)
return .{ first, second }
}
// --- Cast chains ---
pub const Header = struct {
magic u32,
len u32,
}
// Spell #ptrCast outermost: the lowered Zig is then already in the order
// zig fmt canonicalizes to.
pub fn asHeader(raw [*]mut u8) *mut Header {
return #ptrCast(#alignCast(raw))
}
// --- Bit manipulation ---
pub const READY u32 = 1 << 5
pub fn isReady(reg u32) bool {
return reg & READY != 0
}
pub fn green(rgba u32) u8 {
return #truncate((rgba >> 8) & 0xFF)
}
pub fn nextSeq(seq u8) u8 {
return seq +% 1
}
// --- Struct literals and the formatter ---
pub const Config = struct {
name []u8 = "",
retries u8 = 3,
verbose bool = false,
}
// The formatter keeps initializers on one line — write them collapsed.
pub fn defaultConfig() Config {
return .{}
}
pub fn verboseConfig(name []u8) Config {
return .{ .name = name, .retries = 5, .verbose = true }
}
pub var scratch [64]u8 = [_]u8{0} ** 64
// --- JSON ---
pub fn portOf(alloc Allocator, src []u8) !i64 {
doc := try core.json.parse(alloc, src)
value := doc.get("port") orelse return error.MissingPort
return switch value {
.int => |n| n,
else => error.MissingPort,
}
}
test "greeting survives its arena" {
s := try greeting(std.testing.allocator, "port", 2)
defer std.testing.allocator.free(s)
try std.testing.expect(core.mem.eql(u8, s, "hello port, attempt 2"))
}
test "valueOf finds keys and reports missing ones" {
table := [_][]u8{ "host=10.0.0.1", "port=8080" }
v := try valueOf(&table, "port")
try std.testing.expect(core.mem.eql(u8, v, "8080"))
try std.testing.expectError(error.NotFound, valueOf(&table, "user"))
try std.testing.expectEqual(8080, portOrDefault("8080"))
try std.testing.expectEqual(8080, portOrDefault("not a number"))
}
test "dupePair hands back two independent copies" {
pair := try dupePair(std.testing.allocator, "a", "bb")
defer {
std.testing.allocator.free(pair[0])
std.testing.allocator.free(pair[1])
}
try std.testing.expect(core.mem.eql(u8, pair[1], "bb"))
}
test "asHeader reinterprets raw bytes in place" {
var buf [8]u8 align(4) = [_]u8{0} ** 8
h := asHeader(&buf)
h.magic = 0x464c5348
try std.testing.expectEqual(0x48, buf[0])
}
test "bit recipes" {
try std.testing.expect(isReady(READY))
try std.testing.expect(!isReady(0))
try std.testing.expectEqual(0x34, green(0x00123456))
try std.testing.expectEqual(0, nextSeq(255))
}
test "struct literal recipes" {
cfg := verboseConfig("uart0")
try std.testing.expect(cfg.verbose)
try std.testing.expectEqual(5, cfg.retries)
try std.testing.expectEqual(3, defaultConfig().retries)
try std.testing.expectEqual(0, scratch[10])
}
test "portOf reads a JSON document" {
var arena = core.arena.ArenaAllocator.init(std.testing.allocator)
defer arena.deinit()
n := try portOf(arena.allocator(), "{\"host\":\"example\",\"port\":8080}")
try std.testing.expectEqual(8080, n)
}