{
  "schema_version": "1.0.0",
  "source": {
    "repository": "https://github.com/aardappel/goose",
    "revision": "eadca409f68210893f366e60d0c2f0dc29a339be",
    "path": "docs/tutorial.md",
    "blob_sha": "f7fbc2ebe39765a360c5ab342ef08bb50c2c8f4a",
    "url": "https://github.com/aardappel/goose/blob/eadca409f68210893f366e60d0c2f0dc29a339be/docs/tutorial.md",
    "source_url": "https://aardappel.github.io/goose/docs/tutorial.html",
    "license": "Apache-2.0",
    "source_goose_blocks": 59
  },
  "examples": [
    {
      "ordinal": 1,
      "anchor": "example-01",
      "original_heading": "## 1. The core idea",
      "original_line": 46,
      "goose": "var words: u8[][>..] = [];\nfor i in 5 { words.push(str(\"word\", i)); }\n",
      "rust": "let mut words: Vec<Vec<u8>> = Vec::new();\nfor i in 0..5 { words.push(format!(\"word{i}\").into_bytes()); }\n",
      "rust_context_url": "rust/001.rs",
      "rust_support_urls": [],
      "semantic_note": "Same values, different storage: each inner Vec owns a separate byte buffer; this is not Goose's packed inline array.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "9257bed798c5c44cc32171e71b46b34d8a247b375a4da52194b060cfd16bbdde",
      "rust_sha256": "93796632b324dbd4b83d8c75b3191a62d5533e0617630f44406a4edad9468e28"
    },
    {
      "ordinal": 2,
      "anchor": "example-02",
      "original_heading": "## 2. Running something",
      "original_line": 112,
      "goose": "fn main() {\n    print(\"hello, goose\");\n}\n",
      "rust": "fn main() {\n    println!(\"hello, goose\");\n}\n",
      "rust_context_url": "rust/002.rs",
      "rust_support_urls": [],
      "semantic_note": null,
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "63f3013c398af003af9f3d1986f6d208129ec8a521d470f231ee80d509365c30",
      "rust_sha256": "bc54530a1394d23e38521492a0bc8ff106c0870cc9dc9250982b4c65510092b4"
    },
    {
      "ordinal": 3,
      "anchor": "example-03",
      "original_heading": "## 2. Running something",
      "original_line": 122,
      "goose": "print(\"answer=\", 42, \" ratio=\", 0.75, \" yes=\", 3 > 2);\n",
      "rust": "println!(\"answer={} ratio={} yes={}\", 42, 0.75, 3 > 2);\n",
      "rust_context_url": "rust/003.rs",
      "rust_support_urls": [],
      "semantic_note": null,
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "e519ede5038c7234d3f9eb2adf24a7136a8cdf470b3e6c64c5a1b4408776b5bf",
      "rust_sha256": "62e9ed93dc4ce94113777502d3720fb73fea26630bb566d85831314a3ea8d676"
    },
    {
      "ordinal": 4,
      "anchor": "example-04",
      "original_heading": "## 3. Familiar syntax",
      "original_line": 138,
      "goose": "let answer = 42;\nvar count: i32 = 0;\nlet ratio = 0.75;\ncount += 1;\ncount++;              // a statement, not an expression\n",
      "rust": "let answer = 42_i64;\nlet mut count: i32 = 0;\nlet ratio = 0.75_f64;\ncount += 1;\ncount += 1; // Rust has no ++ statement.\n",
      "rust_context_url": "rust/004.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust let mut permits rebinding and mutation; Goose let can still allow mutation of contents.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "144e32ae3f3953f64f85945520fa97ea72c19843203c75b1be896789180a0414",
      "rust_sha256": "40a308795e340390e02420528c6893ec9bd90958a55e3d5fa545cee2847478a1"
    },
    {
      "ordinal": 5,
      "anchor": "example-05",
      "original_heading": "## 3. Familiar syntax",
      "original_line": 153,
      "goose": "struct Unit { kind: i32, hp: i32 = 100, x: f32, y: f32, name: u8[] }\n\nlet scout = Unit { kind: 2, x: 1.5, .. };   // hp 100, y 0, name \"\"\nvar selected: Unit;                         // kind 0, hp 100, x 0, y 0, name \"\"\nvar log: u8[][>..];                         // empty\n",
      "rust": "struct Unit { kind: i32, hp: i32, x: f32, y: f32, name: Vec<u8> }\nimpl Default for Unit {\n    fn default() -> Self {\n        Self { kind: 0, hp: 100, x: 0.0, y: 0.0, name: Vec::new() }\n    }\n}\nlet scout = Unit { kind: 2, x: 1.5, ..Unit::default() };\nlet mut selected = Unit::default();\nlet mut log: Vec<Vec<u8>> = Vec::new();\n",
      "rust_context_url": "rust/005.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust needs an explicit Default implementation for hp=100. These are local bindings; mutable globals need a separate Rust design. Vec fields are indirect, not packed inline.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "529b1a82325b605df9ba42cd2994800808b99128dd5cec7505096b786ad3ce1e",
      "rust_sha256": "ea09d59860d8192e93e90489d7b6e34cf25b03e20e0815e3f78e4ceb56b9e90d"
    },
    {
      "ordinal": 6,
      "anchor": "example-06",
      "original_heading": "## 3. Familiar syntax",
      "original_line": 165,
      "goose": "fn total(xs: i64[:]) -> i64 {\n    var t = 0;\n    for x in xs { t += x; }\n    return t;\n}\n",
      "rust": "fn total(xs: &[i64]) -> i64 {\n    let mut t = 0;\n    for &x in xs { t += x; }\n    t\n}\n",
      "rust_context_url": "rust/006.rs",
      "rust_support_urls": [],
      "semantic_note": null,
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "9e22d171400eb179c4fa2bfef86aad1d93435eb2ae592d5d832df28d5e8e7980",
      "rust_sha256": "afa416ec4a46c2b6d85a244c2c01ac5202dccb7c56573058a4eeb3ee618f690e"
    },
    {
      "ordinal": 7,
      "anchor": "example-07",
      "original_heading": "## 3. Familiar syntax",
      "original_line": 177,
      "goose": "let kind  = if hp > 50 { \"healthy\" } else { \"hurt\" };\nlet level = match hp { 0 => \"dead\", 1..50 => \"low\", _ => \"fine\" };\n",
      "rust": "let kind = if hp > 50 { \"healthy\" } else { \"hurt\" };\nlet level = match hp { 0 => \"dead\", 1..=49 => \"low\", _ => \"fine\" };\n",
      "rust_context_url": "rust/007.rs",
      "rust_support_urls": [],
      "semantic_note": null,
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": "Harness supplies hp at every boundary: 0,1,49,50,51."
      },
      "goose_sha256": "c833b65b55da50208c8820ed4125942d9cc0c210d0a6de2a73525db13d0b11a0",
      "rust_sha256": "8908e71c3a616e8f3dd6ca8cab0240089bc5eab61fe9c64f3b5a4f6a814464f9"
    },
    {
      "ordinal": 8,
      "anchor": "example-08",
      "original_heading": "## 3. Familiar syntax",
      "original_line": 189,
      "goose": "let verdict = block {\n    guard p.alive else { break \"gone\"; }\n    guard p.hp > 0 else { break \"dead\"; }\n    \"standing\"\n};\n",
      "rust": "let verdict = 'verdict: {\n    if !p.alive { break 'verdict \"gone\"; }\n    if p.hp <= 0 { break 'verdict \"dead\"; }\n    \"standing\"\n};\n",
      "rust_context_url": "rust/008.rs",
      "rust_support_urls": [],
      "semantic_note": null,
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": "Harness supplies a live Person with hp=1; other branches also have boundary controls."
      },
      "goose_sha256": "79a964ab668ffdeef619db6bfe14e34530dc928cbeb4f0afc56ecae9702a9ec9",
      "rust_sha256": "23834284cf7fe6dda6a2e5e06cb03ea63a80d13886a4cc24a60e6962bf0227b9"
    },
    {
      "ordinal": 9,
      "anchor": "example-09",
      "original_heading": "## 3. Familiar syntax",
      "original_line": 202,
      "goose": "guard gfx::open(\"demo\", 640, 480, 0) else { return; }\ndefer gfx::close();                 // every way out of this block from here on\n",
      "rust": "struct OnDrop<F: FnOnce()>(Option<F>);\nimpl<F: FnOnce()> Drop for OnDrop<F> {\n    fn drop(&mut self) { if let Some(close) = self.0.take() { close(); } }\n}\nfn demo(open: impl FnOnce(&str, i32, i32, i32) -> bool, close: impl FnOnce()) {\n    if !open(\"demo\", 640, 480, 0) { return; }\n    let _cleanup = OnDrop(Some(close));\n    // Window work goes here; normal scope exits run the guard.\n}\n",
      "rust_context_url": "rust/009.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust uses a Drop guard for scoped cleanup. Supply real graphics callbacks; the harness checks cleanup control flow, not a graphics backend. Process abort does not run Drop.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "3ab9a13abca2d7db863792e3bd43138c06c2ed786557eb93717300e727934b32",
      "rust_sha256": "45447edaf8ff9e172d31fd84111f2bb31cd25448b3632873f84a2bc5186a8b5f"
    },
    {
      "ordinal": 10,
      "anchor": "example-10",
      "original_heading": "## 3. Familiar syntax",
      "original_line": 214,
      "goose": "for i in 3 { }              // 0, 1, 2\nfor i in 10..13 { }         // 10, 11, 12\nfor i: i32 in 0..n { }      // i is an i32; n must widen to one\nfor i: u8 in 0..256 { }     // every u8\nfor x in xs { }             // copies, for fixed-size elements\nfor &x in xs { x *= 2; }    // references: the mutation form\nfor x, i in xs { }          // with the index\n",
      "rust": "for i in 0..3 { }\nfor i in 10..13 { }\nfor i in 0_i32..i32::from(n) { }\nfor i in 0_u8..=u8::MAX { } // all 256 u8 values\nfor &x in &xs { }          // copy fixed-size elements\nfor x in &mut xs { *x *= 2; }\nfor (i, &x) in xs.iter().enumerate() { }\n",
      "rust_context_url": "rust/010.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust makes the widening explicit and enumerate yields (index, element). Mutation needs a mutable borrow.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "6c6f7a4755aabe93b0cbe9006baa7ff482baec80f655e29bd149c29c367b06d3",
      "rust_sha256": "c75021c7e640153bb534268bf7ed86a802ef13de5bf9ea41ea532c4c30fc412b"
    },
    {
      "ordinal": 11,
      "anchor": "example-11",
      "original_heading": "## 3. Familiar syntax",
      "original_line": 228,
      "goose": "fn divide(a: i64, b: i64) -> i64, bool {\n    if b == 0 { return 0, false; }\n    return a / b, true;\n}\n\nlet q, ok = divide(7, 2);\n",
      "rust": "fn divide(a: i64, b: i64) -> (i64, bool) {\n    if b == 0 { return (0, false); }\n    (a / b, true)\n}\nlet (q, ok) = divide(7, 2);\n",
      "rust_context_url": "rust/011.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust returns a tuple; Goose's multiple results are not a tuple type.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "bd069f2793d870285224fd66582c641166983b5aeb70a289823b5fb20d24eec6",
      "rust_sha256": "037311b65d124bec6fc46baa2d7af7db8c1f86661625d1e8723f4cd74f7caec3"
    },
    {
      "ordinal": 12,
      "anchor": "example-12",
      "original_heading": "## 3. Familiar syntax",
      "original_line": 246,
      "goose": "fn limit(x: i64, lo: i64 = 0, hi: i64 = 100) -> i64 {\n    if x < lo { lo } else if x > hi { hi } else { x }\n}\n\nprint(limit(250), \" \", limit(-5, -10));   // 100 -5\n",
      "rust": "fn limit(x: i64, lo: i64, hi: i64) -> i64 {\n    if x < lo { lo } else if x > hi { hi } else { x }\n}\nprintln!(\"{} {}\", limit(250, 0, 100), limit(-5, -10, 100));\n",
      "rust_context_url": "rust/012.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust has no default function arguments; the two calls pass the omitted defaults explicitly.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "817c678e28e2c0a678e142a460034742ebdc85602aa4dbdeb0aa08381ab1c759",
      "rust_sha256": "3ffb89879b553dcae9179f28f6d45e94d09e51a6ecb746d21739907b6ebffad4"
    },
    {
      "ordinal": 13,
      "anchor": "example-13",
      "original_heading": "## 3. Familiar syntax",
      "original_line": 287,
      "goose": "print(-7 % 3, \" \", 7 % -3);       // 2 1\n",
      "rust": "println!(\"{} {}\", (-7_i64).rem_euclid(3), 7_i64.rem_euclid(-3));\n",
      "rust_context_url": "rust/013.rs",
      "rust_support_urls": [],
      "semantic_note": "Use rem_euclid: Rust's % is a truncating remainder, unlike Goose's Euclidean %.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "7edbc9fd01a44340e2f44ea90e24f3b83ad345d73076c443b4063c1ba8b6ff49",
      "rust_sha256": "a98237c087d6ae0ea44722f4dca3922bfd41ccd230945b3245cb4a0a2918fe9e"
    },
    {
      "ordinal": 14,
      "anchor": "example-14",
      "original_heading": "### Leaving a scope frees its data",
      "original_line": 332,
      "goose": "for round in 3 {\n    var scratch: u8[>..] = [];\n    for i in 100000 { scratch.push((i % 256) as! u8); }\n    print(\"round \", round, \": \", scratch.len, \" bytes of scratch\");\n}\n",
      "rust": "for round in 0..3 {\n    let mut scratch: Vec<u8> = Vec::new();\n    for i in 0..100_000 { scratch.push((i % 256) as u8); }\n    println!(\"round {round}: {} bytes of scratch\", scratch.len());\n}\n",
      "rust_context_url": "rust/014.rs",
      "rust_support_urls": [],
      "semantic_note": "The values match, but Rust frees a heap buffer through Drop; it does not rewind Goose data stacks. The cast is in range because of the reduction.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "0f3f488e1f473a7e259aa3aa769bf6920e143f2beb73a28b09d4d5905fa4807d",
      "rust_sha256": "01c143a073dfe2d4454020f3ac53e98dd9fde77cbfb218c1495a4b0b66f9b523"
    },
    {
      "ordinal": 15,
      "anchor": "example-15",
      "original_heading": "### Nothing moves, so references survive growth",
      "original_line": 346,
      "goose": "struct Item { id: i32, weight: f32 }\n\nvar items: Item[>..] = [];\nlet first .= items.push(Item { 1, 0.5 });          // a reference to element 0\nfor i in 2..1000001 { items.push(Item { i as i32, 0.0 }); }\nfirst.weight = 99.5;                               // still valid, a million pushes later\nprint(items.len, \" items, first is \", items[0]);\n",
      "rust": "struct Item { id: i32, weight: f32 }\nlet mut items: Vec<Item> = Vec::new();\nitems.push(Item { id: 1, weight: 0.5 });\nlet first = 0; // retain an index, not a reference across push\nfor i in 2..1_000_001 { items.push(Item { id: i, weight: 0.0 }); }\nitems[first].weight = 99.5;\nprintln!(\"{} items, first is Item {{ {}, {} }}\", items.len(), items[0].id, items[0].weight);\n",
      "rust_context_url": "rust/015.rs",
      "rust_support_urls": [],
      "semantic_note": "Index adaptation: Vec may reallocate, so an ordinary reference into it cannot remain live across push. This preserves the values, not Goose's stable-address guarantee.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "552741b4bf64f8cd7c073bc9f52ccd664eb5e1e2ed08d0516e51d02eb34ab731",
      "rust_sha256": "f6d544421f304548e273142a95c1e3c31ebbd1b2839413526d9088670bfe45a0"
    },
    {
      "ordinal": 16,
      "anchor": "example-16",
      "original_heading": "### Copies are visible",
      "original_line": 374,
      "goose": "var a: i64[>..] = [1, 2, 3];\nvar b = copy(a);      // an explicit, visible O(n) copy\nb.push(4);\n",
      "rust": "let a: Vec<i64> = vec![1, 2, 3];\nlet mut b = a.clone(); // explicit element copy\nb.push(4);\n",
      "rust_context_url": "rust/016.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust assignment of a Vec moves it; borrowing needs & or &mut. Goose's unadorned binding of a non-fixed value instead borrows it.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "278f6298d2af9b951a26aaa4ed9f503fa5f8be9ac0165a83e01186854b8ffd5e",
      "rust_sha256": "2fdeda7bee11986da5dc16b584def377495b4f553e5080cb65fa12da4f408a6c"
    },
    {
      "ordinal": 17,
      "anchor": "example-17",
      "original_heading": "## 5. The array family",
      "original_line": 406,
      "goose": "var fixed: i32[4] = [1, 2, 3, 4];\nlet zeros: f64[8] = [0.0; 8];      // fill form\nlet frozen: i64[] = [7, 8, 9];     // sized once, never changes\n\nvar grow: i64[>..] = [];           // arenas, builders, pools, tree storage\nfor i in 5 { grow.push(i * i); }\n\nvar stack: i64[>..<] = [];         // the one that pops\nstack.push(1); stack.push(2); stack.push(3);\nlet top = stack.pop();\nstack.pop_n(2);                    // drops the last two at once\n\nvar small: u8[..8] = [];           // lives inline anywhere a fixed value can\nsmall.push('h'); small.push('i');\n",
      "rust": "let mut fixed: [i32; 4] = [1, 2, 3, 4];\nlet zeros: [f64; 8] = [0.0; 8];\nlet frozen: Box<[i64]> = vec![7, 8, 9].into_boxed_slice();\nlet mut grow: Vec<i64> = Vec::new();\nfor i in 0..5 { grow.push(i * i); }\nlet mut stack: Vec<i64> = Vec::new();\nstack.push(1); stack.push(2); stack.push(3);\nlet top = stack.pop().unwrap();\nstack.truncate(stack.len() - 2);\nlet mut small = [0_u8; 8];\nlet mut small_len = 0;\nfor &byte in b\"hi\" { small[small_len] = byte; small_len += 1; }\n",
      "rust_context_url": "rust/017.rs",
      "rust_support_urls": [],
      "semantic_note": "Box<[T]> and Vec use indirect heap storage. The bounded byte buffer is an actual inline array plus length; Vec::with_capacity alone would not enforce a maximum. Rust Vec has no grow-only type guarantee.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "0d76ace5da095223734eeccaa155ab7831a5bf0955e204ff90a182719b6f4933",
      "rust_sha256": "ef29b77e69830e13a58da302b4c3905129422ee915446d80da0ec5a2887b99fd"
    },
    {
      "ordinal": 18,
      "anchor": "example-18",
      "original_heading": "## 6. Strings are byte arrays",
      "original_line": 456,
      "goose": "var s: u8[>..] = [];\ns.append(\"hello\");\ns.push(',');\nformat(s, \" world! \", 6 * 7);       // format appends the text of anything\nprint(s, \" [\", s.len, \" bytes]\");\n",
      "rust": "use std::io::{self, Write};\nlet mut s: Vec<u8> = Vec::new();\ns.extend_from_slice(b\"hello\");\ns.push(b',');\nwrite!(&mut s, \" world! {}\", 6 * 7).unwrap();\nlet mut out = io::stdout().lock();\nout.write_all(&s).unwrap();\nwriteln!(&mut out, \" [{} bytes]\", s.len()).unwrap();\n",
      "rust_context_url": "rust/018.rs",
      "rust_support_urls": [],
      "semantic_note": "Vec<u8> preserves byte data but uses Rust heap allocation; the Rust formatting operation explicitly handles its I/O result.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "af2469f834a1b1ddd9f9dc1efe506a91190ff8113494e1df5904888b9e4e77d9",
      "rust_sha256": "8c8c2dd640e2bbde4835cc54edd515b3e2e3afbc74da2375a9802c1b8e1e6ccc"
    },
    {
      "ordinal": 19,
      "anchor": "example-19",
      "original_heading": "## 6. Strings are byte arrays",
      "original_line": 472,
      "goose": "print(\"\"\"\n    usage: wc [-l] file\n      -l   count lines only\n    \"\"\");\n",
      "rust": "println!(\"usage: wc [-l] file\\n  -l   count lines only\");\n",
      "rust_context_url": "rust/019.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust raw strings preserve indentation; this literal spells out the newline and spaces instead of Goose's automatic dedent.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "cb6929b824b5631de8f68fb22837d0a918d1d224243346395f4eeed0c8e99185",
      "rust_sha256": "3d8d107e5223e056151adb29d2420d23fb3ce8616cef1d69f35b2fa16a05ad33"
    },
    {
      "ordinal": 20,
      "anchor": "example-20",
      "original_heading": "## 6. Strings are byte arrays",
      "original_line": 486,
      "goose": "words.push(str(\"word\", i));         // written straight into the new element\n",
      "rust": "words.push(format!(\"word{i}\").into_bytes());\n",
      "rust_context_url": "rust/020.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust formats a separately allocated buffer and moves its Vec handle into words; it does not give Goose's final-destination construction guarantee.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": "Harness supplies words: Vec<Vec<u8>> and i=3."
      },
      "goose_sha256": "c9e2ba4fb37c1d303f46a6432d9f61386626e777089a8bd67e68a528fa1db483",
      "rust_sha256": "d3c8c3acab9570fe97d24555d8094c0df4a433ffa34e60ced1f5a71270561510"
    },
    {
      "ordinal": 21,
      "anchor": "example-21",
      "original_heading": "## 6. Strings are byte arrays",
      "original_line": 500,
      "goose": "let line = \"  key = some value  \";\nlet body = trim(line);\nlet eq   = find(body, \"=\");\nprint(\"'\", trim(body[..eq]), \"' -> '\", trim(body[eq + 1..]), \"'\");\n",
      "rust": "use std::io::{self, Write};\nlet line: &[u8] = b\"  key = some value  \";\nlet body = line.trim_ascii();\nlet eq = body.iter().position(|&b| b == b'=').unwrap();\nlet mut out = io::stdout().lock();\nout.write_all(b\"'\").unwrap();\nout.write_all(body[..eq].trim_ascii()).unwrap();\nout.write_all(b\"' -> '\").unwrap();\nout.write_all(body[eq + 1..].trim_ascii()).unwrap();\nout.write_all(b\"'\\n\").unwrap();\n",
      "rust_context_url": "rust/021.rs",
      "rust_support_urls": [],
      "semantic_note": "Byte slices keep the no-copy views and accept arbitrary bytes; trim_ascii supplies the whitespace rule for this input.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "460990132d606dc79bce68642b1ce4ce7da181d18155830922d39bd4bb4372e2",
      "rust_sha256": "ee77ac180ac867233f05c43d2773b5e9382f6c8d192c75f46cef6c0acac7bc79"
    },
    {
      "ordinal": 22,
      "anchor": "example-22",
      "original_heading": "## 6. Strings are byte arrays",
      "original_line": 515,
      "goose": "let parts = split(\"alice,30,paris\", ',');\nprint(parts.len, \" parts: \", parts);      // 3 parts: [\"alice\", \"30\", \"paris\"]\n",
      "rust": "let parts: Vec<&str> = \"alice,30,paris\".split(',').collect();\nprintln!(\"{} parts: {:?}\", parts.len(), parts);\n",
      "rust_context_url": "rust/022.rs",
      "rust_support_urls": [],
      "semantic_note": null,
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "f7bd190c5dfb8a5b345f0c0ce3b27a43738e060d2e3626bc8c7567973115efda",
      "rust_sha256": "5c79dc9a800b2d04860bffa3e9fbc9acf8a609aace3b4cc8fe5fb949330a8f5c"
    },
    {
      "ordinal": 23,
      "anchor": "example-23",
      "original_heading": "## 6. Strings are byte arrays",
      "original_line": 523,
      "goose": "let cmd = words(\"  go   north \");\nprint(cmd.len, \" words: \", cmd);          // 2 words: [\"go\", \"north\"]\n",
      "rust": "let cmd: Vec<&str> = \"  go   north \".split_ascii_whitespace().collect();\nprintln!(\"{} words: {:?}\", cmd.len(), cmd);\n",
      "rust_context_url": "rust/023.rs",
      "rust_support_urls": [],
      "semantic_note": null,
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "a89777aa3732044e180752682183cdedd3f51212cb0be1fe4c191c7db9f43e14",
      "rust_sha256": "1ad195932cc9de33845d6a73ead13c5a18244854646bfb7cc327b733ef84f187"
    },
    {
      "ordinal": 24,
      "anchor": "example-24",
      "original_heading": "## 6. Strings are byte arrays",
      "original_line": 531,
      "goose": "struct Person { name: u8[..16], age: i32 }\n\n// A `format` overload makes print/str/format render a Person your way.\nfn format(out: u8[>..]&, p: Person) { format(out, p.name, \" (\", p.age, \")\"); }\n\nvar people: Person[>..] = [];\npeople.push(Person { name: \"ada\", age: 36 });\npeople.push(Person { name: \"grace\", age: 45 });\nvar p = Person { name: \"\", age: 20 };\nformat(p.name, \"linus\");        // a limited array is a builder too, up to capacity\npeople.push(p);\nprint(people);\n",
      "rust": "use small_bytes::SmallBytes; // checked inline [u8; N] + length helper\nstruct Person { name: SmallBytes<16>, age: i32 }\nimpl std::fmt::Display for Person {\n    fn fmt(&self, out: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let name = std::str::from_utf8(self.name.as_bytes()).map_err(|_| std::fmt::Error)?;\n        write!(out, \"{} ({})\", name, self.age)\n    }\n}\nlet mut people: Vec<Person> = Vec::new();\npeople.push(Person { name: SmallBytes::new(b\"ada\"), age: 36 });\npeople.push(Person { name: SmallBytes::new(b\"grace\"), age: 45 });\nlet mut p = Person { name: SmallBytes::new(b\"\"), age: 20 };\np.name.append(b\"linus\");\npeople.push(p);\nprintln!(\"[{}]\", people.iter().map(ToString::to_string).collect::<Vec<_>>().join(\", \"));\n",
      "rust_context_url": "rust/024.rs",
      "rust_support_urls": [
        "rust/support/small_bytes.rs"
      ],
      "semantic_note": "SmallBytes is the accompanying safe fixed-capacity byte helper, not Vec::with_capacity. Rust padding/length metadata differ from Goose packing; Display here formats the UTF-8 names shown.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "aeefa4d242e305acb4b536b64e414ca472c29a2f5626c10a4e8a5a023b92eb72",
      "rust_sha256": "65504d58adce1644e1db0a2137f72db95c6142b47c8c8ad0bb7b7772f5756e9c"
    },
    {
      "ordinal": 25,
      "anchor": "example-25",
      "original_heading": "## 6. Strings are byte arrays",
      "original_line": 555,
      "goose": "let who = if people.len > 3 { \"a crowd\" } else { people[1].name };\nprint(who);                             // grace\n",
      "rust": "use std::io::{self, Write};\nlet who: &[u8] = if people.len() > 3 { b\"a crowd\" } else { people[1].name.as_bytes() };\nlet mut out = io::stdout().lock();\nout.write_all(who).unwrap();\nout.write_all(b\"\\n\").unwrap();\n",
      "rust_context_url": "rust/025.rs",
      "rust_support_urls": [
        "rust/support/small_bytes.rs"
      ],
      "semantic_note": null,
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": "Harness supplies the three Person values from counterpart 24."
      },
      "goose_sha256": "f966b3abf6aba92fd4860b1198f7d1e05b1524f89e47f40d7184fdefab63db05",
      "rust_sha256": "40e537084dc12b3412b4efd4644f21eb20725e2ef3f77e12dd7ff5e31589175d"
    },
    {
      "ordinal": 26,
      "anchor": "example-26",
      "original_heading": "## 7. Slices that cannot dangle",
      "original_line": 568,
      "goose": "fn total(xs: i64[:]) -> i64 { var t = 0; for x in xs { t += x; } return t; }\n\ntotal(fixed);         // a T[k]\ntotal(grow);          // a T[>..]\ntotal(grow[1..4]);    // a sub-range\ntotal(grow[^2..]);    // ^k counts from the end\n",
      "rust": "fn total(xs: &[i64]) -> i64 { xs.iter().sum() }\ntotal(&fixed);\ntotal(&grow);\ntotal(&grow[1..4]);\ntotal(&grow[grow.len() - 2..]);\n",
      "rust_context_url": "rust/026.rs",
      "rust_support_urls": [],
      "semantic_note": null,
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": "Harness supplies i64 arrays of sufficient length. The earlier i32[4] example would need element conversion, not a cast of &[i32] to &[i64]."
      },
      "goose_sha256": "0b750c7726a6f895191868e19fc0940bdb821c30155277186b1a8cb14787a9b7",
      "rust_sha256": "d194930de06799e7984a91438aa20b0eb93e1bab08179a5b17f58379f27c8e74"
    },
    {
      "ordinal": 27,
      "anchor": "example-27",
      "original_heading": "## 7. Slices that cannot dangle",
      "original_line": 582,
      "goose": "let view: const i64[:] = fixed;   // fixed itself, not a copy\nfixed[0] = 99;\nprint(view[0]);                   // 99\n",
      "rust": "use std::cell::Cell;\nlet fixed = [1_i64, 2, 3, 4].map(Cell::new);\nlet view: &[Cell<i64>] = &fixed;\nfixed[0].set(99);\nprintln!(\"{}\", view[0].get());\n",
      "rust_context_url": "rust/027.rs",
      "rust_support_urls": [],
      "semantic_note": "Cell adaptation: a shared &[Cell<i64>] supports this aliasing mutation. An ordinary &[i64] kept live across fixed[0] = 99 is rejected by Rust.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "166559a047e65eb59ed77b35688a9003b425d72e07569a1d8f6998a9c5d8d87e",
      "rust_sha256": "238a597593eb326d7dd19cdfc3d60406bb5d731c9782dde6479d6a0bf902889e"
    },
    {
      "ordinal": 28,
      "anchor": "example-28",
      "original_heading": "## 7. Slices that cannot dangle",
      "original_line": 606,
      "goose": "var line: u8[>..] = [];\n// ...\nlet w = line[..5];\nprint(w);\nline.clear();        // fine: w's last use is behind the clear\n",
      "rust": "use std::io::{self, Write};\nlet mut line: Vec<u8> = Vec::new();\n// ... fill line before slicing ...\nline.extend_from_slice(b\"hello\");\nlet w = &line[..5];\nlet mut out = io::stdout().lock();\nout.write_all(w).unwrap();\nout.write_all(b\"\\n\").unwrap();\nline.clear(); // w's last use is behind the clear\n",
      "rust_context_url": "rust/028.rs",
      "rust_support_urls": [],
      "semantic_note": "The original ellipsis must fill at least five bytes before slicing; this counterpart explicitly supplies hello. Rust also permits clear after the borrow's last use.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "3c9b43062c70b0a655cff94613d13eb67906523fd2d2ce0a0e55cc518a7c7ce4",
      "rust_sha256": "5cf05102309007f8e884195c4eef5b2c7afa6b876d9769e3e2f2649fa96efc63"
    },
    {
      "ordinal": 29,
      "anchor": "example-29",
      "original_heading": "## 7. Slices that cannot dangle",
      "original_line": 622,
      "goose": "let text = \"the quick brown fox jumps over the lazy dog the fox\";\nvar counts = dictionary<const u8[:], i32> {};\neach_split(text, ' ') { counts.update(it, 0) { it += 1; }; };\nprint(counts.count, \" distinct words\");\n",
      "rust": "use std::collections::HashMap;\nlet text = \"the quick brown fox jumps over the lazy dog the fox\";\nlet mut counts: HashMap<&str, i32> = HashMap::new();\nfor word in text.split(' ') { *counts.entry(word).or_insert(0) += 1; }\nprintln!(\"{} distinct words\", counts.len());\n",
      "rust_context_url": "rust/029.rs",
      "rust_support_urls": [],
      "semantic_note": null,
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "3d493ed230ff2821978dc43c6e8fd58d3bf14f8f69911b141ba0b2a08ace5a6f",
      "rust_sha256": "5edd18d5b88ee4b613a33f9e728ffd23e824a3ac1494bf6a2d72e22a8bd4d76b"
    },
    {
      "ordinal": 30,
      "anchor": "example-30",
      "original_heading": "## 8. Nested data stays inline",
      "original_line": 652,
      "goose": "struct Item  { sku: u8[varint], qty: varint, cents: varint }\nstruct Order { id: varint, customer: u8[varint], items: Item[varint] }\n",
      "rust": "#[derive(Debug)]\nstruct Item { sku: Vec<u8>, qty: i64, cents: i64 }\n#[derive(Debug)]\nstruct Order { id: i64, customer: Vec<u8>, items: Vec<Item> }\n",
      "rust_context_url": "rust/030.rs",
      "rust_support_urls": [],
      "semantic_note": "Vec<u8> fields preserve byte strings, but Rust stores separate heap buffers and fixed-width integers; these are not inline LEB128 records.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "23d712fb27603cf73ce6cda657bdb92ef2aeb33d113841e230c6d60e6310a9d0",
      "rust_sha256": "e23080e5368223184adf4c9d1722e8797918da46edac6ffa077070b991f2e070"
    },
    {
      "ordinal": 31,
      "anchor": "example-31",
      "original_heading": "## 8. Nested data stays inline",
      "original_line": 662,
      "goose": "// \"SKU:qty:cents;...\" -> items, built straight into the field that gets them\nfn parse_items(field: u8[:]) -> Item[>..] {\n    var items: Item[>..] = [];\n    each_split(field, ';') {\n        let p = split(it, ':');\n        let qty, ok1 = parse_int(p[1]);\n        let cents, ok2 = parse_int(p[2]);\n        assert(ok1 && ok2);\n        items.push(Item { sku: p[0], qty: qty, cents: cents });\n    };\n    return items;\n}\n\nvar book: Order[>..] = [];\nbook.push(Order { id: 1001, customer: \"alice\",\n                  items: parse_items(\"SKU-441:2:1999;SKU-7:1:500\") });\n\nfor o in book {\n    var t = 0;\n    for it in o.items { t += it.qty * it.cents; }\n    print(o.customer, \" owes \", t, \" cents over \", o.items.len, \" items\");\n}\n",
      "rust": "fn parse_items(field: &[u8]) -> Vec<Item> {\n    field.split(|&b| b == b';').map(|record| {\n        let p: Vec<&[u8]> = record.split(|&b| b == b':').collect();\n        let qty = std::str::from_utf8(p[1]).unwrap().parse::<i64>().unwrap();\n        let cents = std::str::from_utf8(p[2]).unwrap().parse::<i64>().unwrap();\n        Item { sku: p[0].to_vec(), qty, cents }\n    }).collect()\n}\nlet mut book: Vec<Order> = Vec::new();\nbook.push(Order { id: 1001, customer: b\"alice\".to_vec(),\n                  items: parse_items(b\"SKU-441:2:1999;SKU-7:1:500\") });\nfor o in &book {\n    let t: i64 = o.items.iter().map(|item| item.qty * item.cents).sum();\n    use std::io::Write;\n    let mut out=std::io::stdout().lock();\n    out.write_all(&o.customer).unwrap();\n    writeln!(&mut out,\" owes {t} cents over {} items\",o.items.len()).unwrap();\n}\n",
      "rust_context_url": "rust/031.rs",
      "rust_support_urls": [],
      "semantic_note": "Same records and total, with owned byte copies and separate Vec allocations. The numeric fields shown are UTF-8/ASCII; parse failures panic here, matching the example's assertion for invalid numbers.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "4a240ed66c294d37b1238a56674cfc8513411397551e1c71bca3d8b26d647fbb",
      "rust_sha256": "6b02cc0cc45a63955555f11a8bfced7346881cefae881962add7f9321d04d6b9"
    },
    {
      "ordinal": 32,
      "anchor": "example-32",
      "original_heading": "## 8. Nested data stays inline",
      "original_line": 722,
      "goose": "for o in book { print(o); }     // fine\nprint(book[0]);                 // error: arrays of variable-size elements\n                                // cannot be indexed, only iterated\n",
      "rust": "for o in &book { println!(\"{o:?}\"); }\nprintln!(\"{:?}\", book[0]); // valid: Vec<Order> has fixed-size, indexable elements\n",
      "rust_context_url": "rust/032.rs",
      "rust_support_urls": [],
      "semantic_note": "Contrast: Rust's Vec<Order> permits indexing because every Order has a fixed-size Vec handle. Goose rejects book[0] for its packed variable-size elements. This Rust layout uses separate buffers.",
      "relationship": "representation_contrast",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": "The harness supplies a single Order and verifies iteration plus indexing, rather than manufacturing a Rust rejection."
      },
      "goose_sha256": "cf4e26702cfe4db409c920c49550be9aeedd14d3e27d5c48388b5dc45d6119ab",
      "rust_sha256": "dc917ebace503424eac8d9a7fd469c7f7703e3f06d145255b45a809f3fb58480"
    },
    {
      "ordinal": 33,
      "anchor": "example-33",
      "original_heading": "## 9. Enums, in two sizes",
      "original_line": 741,
      "goose": "enum Shape { Circle { r: f64 }, Rect { w: f64, h: f64 }, Dot }\n",
      "rust": "#[derive(Debug)]\nenum Shape { Circle { r: f64 }, Rect { w: f64, h: f64 }, Dot }\n",
      "rust_context_url": "rust/033.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust enums have a fixed size and alignment/padding rules; do not infer Goose's 17-byte layout from this declaration.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "fc0c82576641cf509cd8b8b791640ed36410cb73a9502407bcfed95910533b3f",
      "rust_sha256": "0e235748d560b67eb1f5332ab92990931739381d982f4846d955cf004f08e055"
    },
    {
      "ordinal": 34,
      "anchor": "example-34",
      "original_heading": "## 9. Enums, in two sizes",
      "original_line": 753,
      "goose": "var shapes: Shape[>..] = [];\nshapes.push(Shape.Circle { r: 1.0 });\nshapes.push(Shape.Rect { w: 2.0, h: 3.0 });\nshapes.push(Shape.Dot);\nshapes[2] = Shape.Rect { w: 1.0, h: 1.0 };      // a different variant, in place\n",
      "rust": "let mut shapes: Vec<Shape> = Vec::new();\nshapes.push(Shape::Circle { r: 1.0 });\nshapes.push(Shape::Rect { w: 2.0, h: 3.0 });\nshapes.push(Shape::Dot);\nshapes[2] = Shape::Rect { w: 1.0, h: 1.0 };\n",
      "rust_context_url": "rust/034.rs",
      "rust_support_urls": [],
      "semantic_note": null,
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "ef60c570f57442c1a4b2ba88fd0199039210b496ee0be2371ce976b125c69987",
      "rust_sha256": "079edbdf7a1509aa557ad048e7679f7463986db97749c5a6229baa68a2977265"
    },
    {
      "ordinal": 35,
      "anchor": "example-35",
      "original_heading": "## 9. Enums, in two sizes",
      "original_line": 768,
      "goose": "var packed: Shape..[>..] = [];\npacked.push(Shape.Circle { r: 1.0 });\npacked.push(Shape.Dot);\npacked.push(Shape.Rect { w: 2.0, h: 3.0 });\n\nfor s in packed {\n    match s {\n        Rect &r => { r.w += 1.0; },     // edits the payload in place, inside the array\n        _ => {},\n    }\n}\n",
      "rust": "let mut packed: Vec<Shape> = Vec::new(); // name only; Rust elements are fixed-size\npacked.push(Shape::Circle { r: 1.0 });\npacked.push(Shape::Dot);\npacked.push(Shape::Rect { w: 2.0, h: 3.0 });\nfor s in &mut packed {\n    if let Shape::Rect { w, .. } = s { *w += 1.0; }\n}\n",
      "rust_context_url": "rust/035.rs",
      "rust_support_urls": [],
      "semantic_note": "Closest safe adaptation: Vec<Shape> is not packed variable-mode storage. Rust can borrow a payload while its exclusive borrow prevents conflicting replacement; Goose instead forbids changing a variable-mode value's variant.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "e126c77c269e9d4f6e2a9e70dd0d82a9e48192ce21d70e5036284b2456b81d29",
      "rust_sha256": "fd6edc9958e228e6059ad1d10746d95338f178d14e70eb4f2c1a2a292344e4a0"
    },
    {
      "ordinal": 36,
      "anchor": "example-36",
      "original_heading": "### `match`, and match written as functions",
      "original_line": 798,
      "goose": "fn name(s: Shape) -> u8[:] {\n    match s {\n        Circle c => \"circle\",\n        Rect r => if r.w == r.h { \"square\" } else { \"rectangle\" },\n        _ => \"other\",\n    }\n}\n",
      "rust": "fn name(s: &Shape) -> &'static str {\n    match s {\n        Shape::Circle { .. } => \"circle\",\n        Shape::Rect { w, h } => if w == h { \"square\" } else { \"rectangle\" },\n        _ => \"other\",\n    }\n}\n",
      "rust_context_url": "rust/036.rs",
      "rust_support_urls": [],
      "semantic_note": null,
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "5129ea5c593ff6f4211bf55768492fb208cf7f4d13704af999f4779b233860c8",
      "rust_sha256": "91ac28c7d52863664cfadd47955623442ae11993a455b633dfd8a545098b00fa"
    },
    {
      "ordinal": 37,
      "anchor": "example-37",
      "original_heading": "### `match`, and match written as functions",
      "original_line": 817,
      "goose": "let GROUND = 0;\nlet SHALLOW = 1;\nlet DEEP = 4;\nlet LAVA = 7;\n\nfn terrain(t: i64) -> u8[:] {\n    match t {\n        GROUND => \"ground\",\n        SHALLOW..DEEP => \"water\",\n        LAVA, 10..12 => \"hot\",\n        _ => \"rock\",\n    }\n}\n",
      "rust": "const GROUND: i64 = 0;\nconst SHALLOW: i64 = 1;\nconst DEEP: i64 = 4;\nconst LAVA: i64 = 7;\nfn terrain(t: i64) -> &'static str {\n    match t {\n        GROUND => \"ground\",\n        x if (SHALLOW..DEEP).contains(&x) => \"water\", // 1, 2, 3\n        LAVA | 10..=11 => \"hot\",                    // 7, 10, 11\n        _ => \"rock\",\n    }\n}\n",
      "rust_context_url": "rust/037.rs",
      "rust_support_urls": [],
      "semantic_note": "The guard preserves SHALLOW..DEEP's excluded end, and 10..=11 preserves Goose's half-open 10..12.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "71f8f392bef4becbc7f5a9a0034b018df1a272be898d193a607c9162cd1149f7",
      "rust_sha256": "cb7481a95d1f2c3197e399a920b2b7a0d7ea3695735f644e219d2f43bf0df355"
    },
    {
      "ordinal": 38,
      "anchor": "example-38",
      "original_heading": "### `match`, and match written as functions",
      "original_line": 836,
      "goose": "fn area(s: Shape.Circle) -> f64 { 3.14159 * s.r * s.r }\nfn area(s: Shape.Rect) -> f64   { s.w * s.h }\nfn area(s: Shape.Dot) -> f64    { 0.0 }\n\nfor s in shapes { print(s, \" area \", area(s)); }\n",
      "rust": "fn area(s: &Shape) -> f64 {\n    match s {\n        Shape::Circle { r } => 3.14159 * r * r,\n        Shape::Rect { w, h } => w * h,\n        Shape::Dot => 0.0,\n    }\n}\nfor s in &shapes {\n    let description = match s {\n        Shape::Circle { r } => format!(\"Shape.Circle {{ {r} }}\"),\n        Shape::Rect { w, h } => format!(\"Shape.Rect {{ {w}, {h} }}\"),\n        Shape::Dot => \"Shape.Dot\".to_owned(),\n    };\n    println!(\"{description} area {}\", area(s));\n}\n",
      "rust_context_url": "rust/038.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust uses one exhaustive match: enum variants are not independently named parameter types for overloading. The explicit description preserves the Goose-style display for this fixture.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "2e4e75e69d02d4e940ba5849d33d251870c0184f90b32c48bf25ba9943d593ca",
      "rust_sha256": "8c92d4b319a92a6763e812fb959bdd984db78b5ac614770dd32c9a57a8513e56"
    },
    {
      "ordinal": 39,
      "anchor": "example-39",
      "original_heading": "## 10. Linking things without pointers",
      "original_line": 876,
      "goose": "struct Node { key: i32, count: i32 = 1, left: Node&<u32>?, right: Node&<u32>? }\n\nfn insert(pool: Node[>..]&, key: i32) {\n    if pool.len == 0 { pool.push(Node { key: key }); return; }\n    var cur .= pool[0];                  // .= binds the element; = would copy it\n    loop {\n        if key == cur.key { cur.count += 1; return; }\n        if key < cur.key {\n            let l = cur.left;\n            if l { cur .= l; continue; }             // narrowed by `if`: l is a Node&\n            cur.left .= pool.push(Node { key: key });   // the push cannot move cur\n            return;\n        }\n        let r = cur.right;\n        if r { cur .= r; continue; }\n        cur.right .= pool.push(Node { key: key });\n        return;\n    }\n}\n",
      "rust": "struct Node { key: i32, count: i32, left: Option<usize>, right: Option<usize> }\nfn insert(pool: &mut Vec<Node>, key: i32) {\n    if pool.is_empty() {\n        pool.push(Node { key, count: 1, left: None, right: None });\n        return;\n    }\n    let mut cur = 0;\n    loop {\n        if key == pool[cur].key { pool[cur].count += 1; return; }\n        let left = key < pool[cur].key;\n        let child = if left { pool[cur].left } else { pool[cur].right };\n        if let Some(next) = child { cur = next; continue; }\n        let next = pool.len();\n        pool.push(Node { key, count: 1, left: None, right: None });\n        if left { pool[cur].left = Some(next); } else { pool[cur].right = Some(next); }\n        return;\n    }\n}\n",
      "rust_context_url": "rust/039.rs",
      "rust_support_urls": [],
      "semantic_note": "Indices replace stable/self-relative references. Option<usize> is not a four-byte link, and this Rust layout is not a relocatable Goose byte image.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "07193be624e7eb0a090b9c34680126fb2f43bbf26e096aaacc71563cad8661af",
      "rust_sha256": "81bce4675d0f0bec5e4d8d9ae11455a5e0c7441da104adfeb6b15afbb9b3fd59"
    },
    {
      "ordinal": 40,
      "anchor": "example-40",
      "original_heading": "### `self`, and sentinels",
      "original_line": 933,
      "goose": "import slot_pool;\n\nstruct Node { val: i64, prev: Node&<u32 in pool.items>, next: Node&<u32 in pool.items> }\n\nvar pool = slot_pool<Node> {};\nlet head .= pool.alloc_with() { Node { val: 0, prev: self, next: self } };\n",
      "rust": "use slot_pool::SlotPool;\nstruct Node { val: i64, prev: usize, next: usize }\nlet mut pool: SlotPool<Node> = SlotPool::new();\nlet head = pool.items.len();\npool.alloc(Node { val: 0, prev: head, next: head });\n",
      "rust_context_url": "rust/040.rs",
      "rust_support_urls": [
        "rust/support/slot_pool.rs"
      ],
      "semantic_note": "An index chosen before allocation makes a safe sentinel. SlotPool is the accompanying Vec/freelist helper; its links are indices, not Goose's pool-relative byte offsets or global owner.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "95f90651537fad6f9fbafe569b9193579087d29197dfec8614208e953692e2a7",
      "rust_sha256": "51b17751b38e8a458abd6121ae18d003eac3feeac1b84fa9dad9c18be8bce55c"
    },
    {
      "ordinal": 41,
      "anchor": "example-41",
      "original_heading": "### `self`, and sentinels",
      "original_line": 950,
      "goose": "fn insert_after(p: Node&, v: i64) -> Node& {\n    let n .= pool.alloc_ref(Node { val: v, prev: p, next: p.next });\n    n.next.prev .= n;\n    p.next .= n;\n    return n;\n}\n\nfn remove(n: Node&) {\n    n.prev.next .= n.next;\n    n.next.prev .= n.prev;\n    pool.free(pool.items.index_of(n));\n}\n\nfn is_end(n: Node&) -> bool { n .== head }\n",
      "rust": "fn insert_after(pool: &mut SlotPool<Node>, p: usize, v: i64) -> usize {\n    let next = pool.items[p].next;\n    let n = pool.alloc(Node { val: v, prev: p, next });\n    pool.items[next].prev = n;\n    pool.items[p].next = n;\n    n\n}\nfn remove(pool: &mut SlotPool<Node>, n: usize) {\n    let (prev, next) = (pool.items[n].prev, pool.items[n].next);\n    pool.items[prev].next = next;\n    pool.items[next].prev = prev;\n    pool.free(n);\n}\nfn is_end(n: usize, head: usize) -> bool { n == head }\n",
      "rust_context_url": "rust/041.rs",
      "rust_support_urls": [
        "rust/support/slot_pool.rs"
      ],
      "semantic_note": "Pass the pool explicitly and use slot indices for identity. Reusing a freed slot changes its logical contents, just as in the Goose pool; the Rust helper is not a compact-offset layout.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "1b70709dcfb71e540665aaad5cb0c331f10f5c7b4004f23420c5fc47accc6ac8",
      "rust_sha256": "276fa1862422ae870c0fe9d1675c16cc5c1280f5e7f7991c5114e44667a1bfac"
    },
    {
      "ordinal": 42,
      "anchor": "example-42",
      "original_heading": "### An index for variable-size elements",
      "original_line": 978,
      "goose": "enum Mark {\n    Circle { r: f64 },\n    Rect { w: f64, h: f64 },\n    Label { text: u8[varint] },\n    Dot,\n}\n\nvar marks: Mark..[>..] = [];\nvar mark_at: (Mark..&<u32 in marks>)[>..] = [];\n\nfn main() {\n    mark_at.push(marks.push(Mark.Label { text: \"hello, goose\" }));\n    mark_at.push(marks.push(Mark.Circle { r: 1.5 }));\n    mark_at.push(marks.push(Mark.Dot));\n    mark_at.push(marks.push(Mark.Rect { w: 2.0, h: 3.0 }));\n    mark_at.push(marks.push(Mark.Label { text: \"x\" }));\n    for i in [3, 0, 4, 1, 2] {\n        match mark_at[i] {\n            Circle c => print(i, \": circle \", c.r),\n            Rect r => print(i, \": rect \", r.w, \" by \", r.h),\n            Label l => print(i, \": label \\\"\", l.text, \"\\\"\"),\n            Dot => print(i, \": dot\"),\n        }\n    }\n}\n",
      "rust": "enum Mark {\n    Circle { r: f64 }, Rect { w: f64, h: f64 },\n    Label { text: Vec<u8> }, Dot,\n}\nfn main() {\n    use std::io::{self, Write};\n    let mut marks: Vec<Mark> = Vec::new();\n    let mut mark_at: Vec<usize> = Vec::new();\n    for mark in [Mark::Label { text: b\"hello, goose\".to_vec() },\n                 Mark::Circle { r: 1.5 }, Mark::Dot,\n                 Mark::Rect { w: 2.0, h: 3.0 }, Mark::Label { text: b\"x\".to_vec() }] {\n        mark_at.push(marks.len()); marks.push(mark);\n    }\n    let mut out=io::stdout().lock();\n    for i in [3, 0, 4, 1, 2] {\n        match &marks[mark_at[i]] {\n            Mark::Circle { r } => writeln!(&mut out,\"{i}: circle {r}\").unwrap(),\n            Mark::Rect { w, h } => writeln!(&mut out,\"{i}: rect {w} by {h}\").unwrap(),\n            Mark::Label { text } => {\n                write!(&mut out,\"{i}: label \\\"\").unwrap();\n                out.write_all(text).unwrap(); writeln!(&mut out,\"\\\"\").unwrap();\n            }\n            Mark::Dot => writeln!(&mut out,\"{i}: dot\").unwrap(),\n        }\n    }\n}\n",
      "rust_context_url": "rust/042.rs",
      "rust_support_urls": [],
      "semantic_note": "Indices preserve lookup order, but Vec<Mark> uses fixed-size enum elements and separate label buffers. It is neither the 44-byte packed layout nor a table of four-byte relative references.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "db9745c7c28b578b50e5cfa837ab70274414d3c9769e91f9b6cc92334c93abf2",
      "rust_sha256": "6fab49f5d6138585a8cbb41b1198ee8c4dd856d2f04834935c44aec5c775dc37"
    },
    {
      "ordinal": 43,
      "anchor": "example-43",
      "original_heading": "## 11. Lifetimes that do not nest",
      "original_line": 1044,
      "goose": "import slot_pool;\nstruct Item { id: i32, weight: f32 }\n\nvar pool = slot_pool<Item> {};\n\nlet s0 = pool.alloc_index(Item { 10, 1.0 });\nlet s1 = pool.alloc_index(Item { 11, 1.0 });\npool.free(s0);\nlet s2 = pool.alloc_index(Item { 12, 2.0 });   // takes slot s0 back\n",
      "rust": "use slot_pool::SlotPool;\nstruct Item { id: i32, weight: f32 }\nlet mut pool: SlotPool<Item> = SlotPool::new();\nlet s0 = pool.alloc(Item { id: 10, weight: 1.0 });\nlet s1 = pool.alloc(Item { id: 11, weight: 1.0 });\npool.free(s0);\nlet s2 = pool.alloc(Item { id: 12, weight: 2.0 });\n",
      "rust_context_url": "rust/043.rs",
      "rust_support_urls": [
        "rust/support/slot_pool.rs"
      ],
      "semantic_note": "The small accompanying Rust helper keeps values alive when slots are returned, then overwrites reused slots. Index identity is memory-safe but is not generation-checked logical identity.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "ffce419d1eb47db84aaff68db435864771cebc60f152ef105fff46066edddb81",
      "rust_sha256": "e2fda085263e46ef75885293e76fc766b33e31fb31783fcb21ae2b54646b6daa"
    },
    {
      "ordinal": 44,
      "anchor": "example-44",
      "original_heading": "## 12. Errors, and `return … from`",
      "original_line": 1116,
      "goose": "fn load(text: u8[:]) -> User[>..], u8[] {\n    var users: User[>..] = [];\n    var lineno = 0;\n    each_split(text, '\\n') {\n        lineno++;\n        if it.len > 0 { users.push(parse_record(it, lineno)); }\n    };\n    return users, \"\";\n}\n\nfn parse_record(line: u8[:], lineno: i64) -> User {\n    let comma = find(line, \",\");\n    guard comma >= 0 else { return [], str(\"line \", lineno, \": expected name,age\") from load; }\n    let age, ok = parse_age(line[comma + 1..]);\n    guard ok else { return [], str(\"line \", lineno, \": bad age\") from load; }\n    return User { name: trim(line[..comma]), age: age };\n}\n",
      "rust": "fn load(text: &[u8]) -> Result<Vec<User>, Vec<u8>> {\n    let mut users = Vec::new();\n    for (number, line) in text.split(|&b| b == b'\\n').enumerate() {\n        if !line.is_empty() { users.push(parse_record(line, number + 1)?); }\n    }\n    Ok(users)\n}\nfn parse_record(line: &[u8], lineno: usize) -> Result<User, Vec<u8>> {\n    let comma = line.iter().position(|&b| b == b',')\n        .ok_or_else(|| format!(\"line {lineno}: expected name,age\").into_bytes())?;\n    let age = parse_age(&line[comma + 1..])\n        .ok_or_else(|| format!(\"line {lineno}: bad age\").into_bytes())?;\n    Ok(User { name: line[..comma].trim_ascii().to_vec(), age })\n}\n",
      "rust_context_url": "rust/044.rs",
      "rust_support_urls": [],
      "semantic_note": "Result and ? explicitly propagate errors through each Rust caller; they are not Goose's nonlocal return from load. The harness supplies the User/parse_age definitions omitted by the original fragment.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": "Explicit minimal missing context: User owns byte name, age is i64; parse_age accepts decimal ages 0..=150. The omitted original helper's complete semantics are not claimed."
      },
      "goose_sha256": "30b3e03a93c2d465bc1b2776921217a9e85d9118a5dc1e62f2a37bdb96070b36",
      "rust_sha256": "0decddcc3fcec39e3aedda0af7785773693e47e34cc07d2c6511bb52bec41e87"
    },
    {
      "ordinal": 45,
      "anchor": "example-45",
      "original_heading": "## 13. Generics, and blocks that disappear",
      "original_line": 1198,
      "goose": "fn twice(x) { x + x }\nfn span<T>(a: T, b: T) -> T { if a > b { a - b } else { b - a } }\n",
      "rust": "fn twice<T: Copy + std::ops::Add<Output = T>>(x: T) -> T { x + x }\nfn span<T: PartialOrd + std::ops::Sub<Output = T>>(a: T, b: T) -> T {\n    if a > b { a - b } else { b - a }\n}\n",
      "rust_context_url": "rust/045.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust checks the generic body against declared bounds; Goose checks it at concrete instantiations. These Rust bounds express the numeric uses shown.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "aa78b5716589310acdeb3bd2fdb481452ca6dab7221bdfe370577cca2400693c",
      "rust_sha256": "eb2cbee8a4c9636aaaa6c1f9f0820e23c12cdbd5968ff9f83f991b5c2153905e"
    },
    {
      "ordinal": 46,
      "anchor": "example-46",
      "original_heading": "## 13. Generics, and blocks that disappear",
      "original_line": 1209,
      "goose": "fn zero<T>() -> T { default<T>() }   // T's default value\n\nlet half = zero<f64>() + 0.5;\n",
      "rust": "fn zero<T: Default>() -> T { T::default() }\nlet half = zero::<f64>() + 0.5;\n",
      "rust_context_url": "rust/046.rs",
      "rust_support_urls": [],
      "semantic_note": null,
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "95236d0369bb927781f7a1bcd7770edfd241a04a3c17a567ace6c1f225b805aa",
      "rust_sha256": "47f795f7740c55cfe1b96795352b2cfa31ad635fdcfbdeb5f50694015fe979b4"
    },
    {
      "ordinal": 47,
      "anchor": "example-47",
      "original_heading": "## 13. Generics, and blocks that disappear",
      "original_line": 1223,
      "goose": "fn describe(x: i64) -> u8[>..]     { str(\"int \", x) }\nfn describe(x: f64) -> u8[>..]     { str(\"float \", x) }\nfn describe(xs: i64[:]) -> u8[>..] { str(xs.len, \" ints, first \", xs[0]) }\n\nprint(describe(7), \"; \", 2.5.describe(), \"; \", xs.describe(), \"; \", describe(xs[2..]));\n",
      "rust": "trait Describe { fn describe(&self) -> String; }\nimpl Describe for i64 {\n    fn describe(&self) -> String { format!(\"int {self}\") }\n}\nimpl Describe for f64 {\n    fn describe(&self) -> String { format!(\"float {self}\") }\n}\nimpl Describe for [i64] {\n    fn describe(&self) -> String { format!(\"{} ints, first {}\", self.len(), self[0]) }\n}\nfn describe<T: Describe + ?Sized>(x: &T) -> String { x.describe() }\nprintln!(\"{}; {}; {}; {}\", describe(&7_i64), 2.5_f64.describe(),\n         xs.describe(), describe(&xs[2..]));\n",
      "rust_context_url": "rust/047.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust uses trait implementations for this overload set. String is appropriate for the formatted numeric text here, but uses separate UTF-8 heap buffers.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": "Harness supplies xs=[1,2,3,4]; the example's first-element access assumes a nonempty slice."
      },
      "goose_sha256": "a73457e7a7ebe897c3c2d5fca90204e67b719acaa4fe19bf573193b576a48368",
      "rust_sha256": "13e22914b6d67e5bab1075a7f8e15d877546569f4ad7295579fdd69d9a719c65"
    },
    {
      "ordinal": 48,
      "anchor": "example-48",
      "original_heading": "## 13. Generics, and blocks that disappear",
      "original_line": 1237,
      "goose": "fn each_pair<T, F>(xs: T[:]) {\n    for i in 0..xs.len - 1 { F(xs[i], xs[i + 1]); }\n}\n\nvar gaps: i64[>..] = [];\neach_pair(xs) { a, b => gaps.push(b - a); };     // writes an enclosing local\n",
      "rust": "fn each_pair<T: Copy>(xs: &[T], mut f: impl FnMut(T, T)) {\n    for pair in xs.windows(2) { f(pair[0], pair[1]); }\n}\nlet mut gaps: Vec<i64> = Vec::new();\neach_pair(&xs, |a, b| gaps.push(b - a));\n",
      "rust_context_url": "rust/048.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust's FnMut closure captures gaps; it is a closure value even when monomorphized/inlined. Rust also allows escaping closures, unlike Goose's static function values.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "ae54340b0e287242a0f1f38d6d326c85d81b56921ec5f8519c25e6b54c3b77a9",
      "rust_sha256": "4f10a559ef3a06ea146906d9eab4d8f32c5cf969ed4683035ce164759880a4be"
    },
    {
      "ordinal": 49,
      "anchor": "example-49",
      "original_heading": "## 13. Generics, and blocks that disappear",
      "original_line": 1251,
      "goose": "let evens   = xs.filter() { it % 2 == 0 };\nlet squares = xs.map()    { it * it };\nlet total   = fold(xs, 0) { acc, x => acc + x };\nsort(xs) { a, b => a > b };\n",
      "rust": "let evens: Vec<i64> = xs.iter().copied().filter(|it| it.rem_euclid(2) == 0).collect();\nlet squares: Vec<i64> = xs.iter().map(|&it| it * it).collect();\nlet total = xs.iter().fold(0, |acc, &x| acc + x);\nxs.sort_by(|a, b| b.cmp(a));\n",
      "rust_context_url": "rust/049.rs",
      "rust_support_urls": [],
      "semantic_note": "collect allocates owned Rust buffers. The reversed comparator preserves the Goose a > b descending order; rem_euclid retains its remainder rule.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "61139568576de2be8239043bf34265df6879fcc1c6b104e113619fcb17909d65",
      "rust_sha256": "fb0f410a0b08faf142c2cd914a92df8986b7e44244ddfa8d8439d0a855496778"
    },
    {
      "ordinal": 50,
      "anchor": "example-50",
      "original_heading": "## 13. Generics, and blocks that disappear",
      "original_line": 1263,
      "goose": "fn each_step<F>(lo: i64, hi: i64, step: i64) {\n    var i = lo;\n    while i < hi { F(i); i += step; }\n}\n\nfn first_multiple_of_7(lo: i64, hi: i64) -> i64 {\n    each_step(lo, hi, 3) { if it % 7 == 0 { return it; } };   // returns from first_multiple_of_7,\n                                                              // not from each_step\n    return -1;\n}\n",
      "rust": "use std::ops::ControlFlow;\nfn each_step<B>(lo: i64, hi: i64, step: i64,\n                mut f: impl FnMut(i64) -> ControlFlow<B>) -> ControlFlow<B> {\n    let mut i = lo;\n    while i < hi { f(i)?; i += step; }\n    ControlFlow::Continue(())\n}\nfn first_multiple_of_7(lo: i64, hi: i64) -> i64 {\n    match each_step(lo, hi, 3, |it| {\n        if it.rem_euclid(7) == 0 { ControlFlow::Break(it) }\n        else { ControlFlow::Continue(()) }\n    }) {\n        ControlFlow::Break(value) => value,\n        ControlFlow::Continue(()) => -1,\n    }\n}\n",
      "rust_context_url": "rust/050.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust explicitly propagates ControlFlow through the callback API. A return inside a Rust closure returns from the closure, not the enclosing function.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "d0460c8a77aa0c71f25628f6f4df40f475a8f58c2454483b5bd726dbced5a91b",
      "rust_sha256": "42d1eabb951a93ef8c57c10f7caa74f5cb3185ed8b770c60c96060c4c3dcffc2"
    },
    {
      "ordinal": 51,
      "anchor": "example-51",
      "original_heading": "## 13. Generics, and blocks that disappear",
      "original_line": 1288,
      "goose": "recursive fn in_order(n: Node&, out: i32[>..]&) {\n    let l = n.left;\n    if l { in_order(l, out); }\n    out.push(n.key);\n    let r = n.right;\n    if r { in_order(r, out); }\n}\n",
      "rust": "fn in_order(n: &Node, out: &mut Vec<i32>) {\n    if let Some(left) = &n.left { in_order(left, out); }\n    out.push(n.key);\n    if let Some(right) = &n.right { in_order(right, out); }\n}\n",
      "rust_context_url": "rust/051.rs",
      "rust_support_urls": [],
      "semantic_note": "The harness supplies an ordinary Box-linked Rust tree. Rust recursion needs no recursive annotation and does not impose Goose's restriction on owned growable locals.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "68d941cf338a9ae2fe1b0f90765cb624accdaac59b10c55b6fbe96012bbbd7f5",
      "rust_sha256": "79cb58b466c7ad12d89b222ee1df3f6e94ed44e3498401517b6bb722ce7c7a25"
    },
    {
      "ordinal": 52,
      "anchor": "example-52",
      "original_heading": "## 13. Generics, and blocks that disappear",
      "original_line": 1303,
      "goose": "recursive fn show(n: Node&, depth: i64) {\n    {\n        var line: u8[>..] = [];\n        for i in depth { line.append(\"  \"); }\n        line.append(str(n.key));\n        print(line);\n    }\n    let l = n.left;\n    if l { show(l, depth + 1); }\n    let r = n.right;\n    if r { show(r, depth + 1); }\n}\n",
      "rust": "fn show(n: &Node, depth: usize) {\n    {\n        let mut line = \"  \".repeat(depth);\n        line.push_str(&n.key.to_string());\n        println!(\"{line}\");\n    }\n    if let Some(left) = &n.left { show(left, depth + 1); }\n    if let Some(right) = &n.right { show(right, depth + 1); }\n}\n",
      "rust_context_url": "rust/052.rs",
      "rust_support_urls": [],
      "semantic_note": "The scope ends before recursion in both versions; Rust drops each heap String instead of rewinding a Goose data stack.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "cbb591355bacb61922e1cdbdb32dc505805a2558511105d7694bfc6e0a136a88",
      "rust_sha256": "1b81e546fd8aabeaf7274940b61eebc4745f958e4c5a7c94c438be8b3b60d3a3"
    },
    {
      "ordinal": 53,
      "anchor": "example-53",
      "original_heading": "### Several tables, one context",
      "original_line": 1330,
      "goose": "struct Node { at: i64, first: i64, next: i64 }   // a source offset, first child, next sibling\n\nstruct Ctx {                 // a slice and three references: fixed-size, cheap to pass\n    source: const u8[:],\n    nodes: Node[>..]&,\n    text: u8[>..]&,\n    scratch: i64[>..<]&,     // the recursion's working stack\n}\n\nrecursive fn walk(c: Ctx&, n: i64, depth: i64) -> i64 {\n    let mark = c.scratch.len;\n    c.scratch.push(depth);                 // this activation's entries, above its callers'\n    c.text.push(c.source[c.nodes[n].at]);\n    var total = c.scratch[mark];\n    var e = c.nodes[n].first;\n    while e >= 0 {\n        total += walk(c, e, depth + 1);\n        e = c.nodes[e].next;\n    }\n    c.scratch.resize(mark);                // gone again before it returns\n    return total;\n}\n\nfn compile(source: const u8[:]) -> i64 {\n    var nodes: Node[>..] = [];\n    var text: u8[>..] = [];\n    var scratch: i64[>..<] = [];\n    nodes.push(Node { at: 0, first: 1, next: -1 });   // a root with two children\n    nodes.push(Node { at: 1, first: -1, next: 2 });\n    nodes.push(Node { at: 2, first: -1, next: -1 });\n    var c = Ctx { source: source, nodes: nodes, text: text, scratch: scratch };\n    let r = walk(c, 0, 1);\n    print(text, \" \", scratch.len);\n    return r;\n}\n",
      "rust": "struct Node { at: i64, first: i64, next: i64 }\nstruct Ctx<'a> {\n    source: &'a [u8], nodes: &'a mut Vec<Node>,\n    text: &'a mut Vec<u8>, scratch: &'a mut Vec<i64>,\n}\nfn walk(c: &mut Ctx<'_>, n: i64, depth: i64) -> i64 {\n    let n = usize::try_from(n).unwrap();\n    let mark = c.scratch.len();\n    c.scratch.push(depth);\n    let at = usize::try_from(c.nodes[n].at).unwrap();\n    c.text.push(c.source[at]);\n    let mut total = c.scratch[mark];\n    let mut e = c.nodes[n].first;\n    while e >= 0 {\n        total += walk(c, e, depth + 1);\n        e = c.nodes[usize::try_from(e).unwrap()].next;\n    }\n    c.scratch.truncate(mark);\n    total\n}\nfn compile(source: &[u8]) -> i64 {\n    let mut nodes=vec![Node {at:0,first:1,next:-1},\n                       Node {at:1,first:-1,next:2}, Node {at:2,first:-1,next:-1}];\n    let mut text=Vec::new(); let mut scratch=Vec::new();\n    let mut c=Ctx {source,nodes:&mut nodes,text:&mut text,scratch:&mut scratch};\n    let r=walk(&mut c,0,1);\n    use std::io::Write;\n    let mut out=std::io::stdout().lock();out.write_all(&text).unwrap();\n    writeln!(&mut out,\" {}\",scratch.len()).unwrap();\n    r\n}\n",
      "rust_context_url": "rust/053.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust explicitly names the borrowed context lifetime and uses exclusive mutable borrows. Vec ownership/drop replaces the Goose storage model, and signed offsets are checked before conversion to usize.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "fd125bdb5936654b11a2b3d0abdc9d63c7ed076590409311613b006229e4f694",
      "rust_sha256": "82dc4bcf808db0b889f38993bd2f79e15dd7d0ddc51de9ba75176f2087fda601"
    },
    {
      "ordinal": 54,
      "anchor": "example-54",
      "original_heading": "## 14. Threads that share nothing",
      "original_line": 1396,
      "goose": "struct Job    { n: i32 }\nstruct Result { n: i32, digits: i32 }\n\nthread_fn worker() {\n    loop {\n        let job = qget<Job>();           // blocks\n        guard job.n >= 0 else { break; } // -1 means stop\n        qput(Result { n: job.n, digits: count_digits(job.n) });\n    }\n}\n\nfn main() {\n    let n = max(1, hardware_threads());\n    for i in 8 { qput(Job { n: (1 << (i * 3)) as i32 }); }\n    for i in n { qput(Job { n: -1 }); }              // one quit job per worker\n    var ids: i64[>..] = [];\n    for i in n { ids.push(thread_spawn(worker)); }\n    var total = 0;\n    for i in 8 { let r = qget<Result>(); total += r.digits; }\n    for id in ids { thread_wait(id); }\n    print(n, \" workers, \", total, \" digits in total\");\n}\n",
      "rust": "use std::sync::mpsc::{self, Receiver, Sender};\nstruct Job { n: i32 }\nstruct Result { n: i32, digits: i32 }\nfn worker(jobs: Receiver<Job>, results: Sender<Result>) {\n    for job in jobs {\n        if job.n < 0 { break; }\n        results.send(Result { n: job.n, digits: count_digits(job.n) }).unwrap();\n    }\n}\nfn main() {\n    let n=std::thread::available_parallelism().map_or(1,usize::from);\n    let (results_tx,results_rx)=mpsc::channel();\n    let mut jobs=Vec::new();let mut ids=Vec::new();\n    for _ in 0..n {\n        let (tx,rx)=mpsc::channel(); let results=results_tx.clone();\n        jobs.push(tx);ids.push(std::thread::spawn(move || worker(rx,results)));\n    }\n    for i in 0..8 { jobs[i % n].send(Job {n:1 << (i*3)}).unwrap(); }\n    for queue in &jobs { queue.send(Job {n:-1}).unwrap(); }\n    let mut total=0;\n    for _ in 0..8 { let r=results_rx.recv().unwrap();total+=r.digits; }\n    for id in ids { id.join().unwrap(); }\n    println!(\"{n} workers, {total} digits in total\");\n}\n",
      "rust_context_url": "rust/054.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust transfers owned messages through per-worker std channels (round-robin dispatch), not Goose's type-selected queue. Rust threads share an address space and do not automatically clone globals. The aggregate result matches; queue scheduling differs.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": "Harness supplies decimal count_digits, missing from the original. The validation process limits its own CPU affinity to at most two CPUs, so this example spawns at most two workers."
      },
      "goose_sha256": "6c9bdbc73825618915a7b5c09b22455b63676d4719e1f42ebef17b70b96fde35",
      "rust_sha256": "5f55d8f60aa4034a200f98f2bd945e013e62a18f484fd31cff5cf48b874da313"
    },
    {
      "ordinal": 55,
      "anchor": "example-55",
      "original_heading": "## 15. Saving and loading data as bytes",
      "original_line": 1442,
      "goose": "struct Node { word: u8[..24], count: i32, left: Node&<u32>?, right: Node&<u32>? }\n\nvar index: Node[>..] = [];\n// ... build the tree ...\n\nvar image: u8[>..] = index.to_bytes();      // a framed image of the array\nvar loaded, ok = from_bytes<Node[>..]>(image);\nprint(\"loaded \", ok, \", \", loaded.len, \" nodes, 'fox' = \", lookup(loaded, \"fox\"));\n",
      "rust": "use index_image::{Node, encode_nodes, decode_nodes, lookup}; // accompanying safe codec\nlet index: Vec<Node> = build_index(); // the omitted tree-building context\nlet mut image: Vec<u8> = encode_nodes(&index).unwrap();\nlet decoded = decode_nodes(&image);\nlet ok = decoded.is_ok();\nlet loaded = decoded.unwrap_or_default();\nprintln!(\"loaded {ok}, {} nodes, 'fox' = {}\", loaded.len(), lookup(&loaded, b\"fox\"));\n",
      "rust_context_url": "rust/055.rs",
      "rust_support_urls": [
        "rust/support/index_image.rs"
      ],
      "semantic_note": "Different-format adaptation: the accompanying codec explicitly encodes bytes and node indices. It is not Goose-wire-compatible and never treats Vec or Rust struct memory bytes as a serialized value.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": "Original tree construction and lookup are omitted. Harness supplies a nine-node BST with fox count=4; codec source specifies its independent RIDX format."
      },
      "goose_sha256": "b6ff0a42c2b80045d873593a688d83439c341028b484c959b7044ebdf27ee44b",
      "rust_sha256": "373f7c9154eee2d498e73b7ca7d00c8d7accd4b8b46a016d9a3321948b80cb33"
    },
    {
      "ordinal": 56,
      "anchor": "example-56",
      "original_heading": "## 15. Saving and loading data as bytes",
      "original_line": 1463,
      "goose": "image[image.len - 3] = 200;                  // tamper with a link\nvar bad, bok = from_bytes<Node[>..]>(image);\nprint(\"accepted: \", bok, \", nodes \", bad.len);\n",
      "rust": "let at = image.len() - 3;\nimage[at] = 200; // corrupt an index in this Rust codec's image\nlet decoded = decode_nodes(&image);\nlet bok = decoded.is_ok();\nlet bad = decoded.unwrap_or_default();\nprintln!(\"accepted: {bok}, nodes {}\", bad.len());\n",
      "rust_context_url": "rust/056.rs",
      "rust_support_urls": [
        "rust/support/index_image.rs"
      ],
      "semantic_note": "This rejection belongs to the different RIDX format from the Rust counterpart above, not Goose's image verifier. The edited child index is out of bounds; valid data edits need separate integrity checks.",
      "relationship": "closest_safe_representation",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "d57c33621bb732929fa4e46d902ac559f0fd276eb7ed663bb8bb6e2ba936585f",
      "rust_sha256": "68772366d9277bbb1521f7dd7d4a3fc11479392f0af8c2ddb25f2347797dd830"
    },
    {
      "ordinal": 57,
      "anchor": "example-57",
      "original_heading": "## 16. Calling C",
      "original_line": 1487,
      "goose": "extern fn cube_root(x: f64) -> f64 = \"cbrt\";\nextern fn hypot(x: f64, y: f64) -> f64;\n\nextern fn crc32_bytes(s: const u8[:]) -> u32;   // a slice in, a scalar out\nextern fn stats_of(xs: i32[:], out: Stats&);    // a struct filled through a reference\nextern fn c_version(out: u8[>..]&);             // a builder C appends to\n",
      "rust": "use std::ffi::c_void;\n#[repr(C, packed)]\nstruct ByteSlice { data: *const u8, len: i64 }\n#[repr(C, packed)]\nstruct I32Slice { data: *mut i32, len: i64 }\n#[repr(C, packed)]\nstruct GooseBuilder { header: *mut c_void, stack: *mut c_void }\nunsafe extern \"C\" {\n    #[link_name = \"cbrt\"] fn cube_root(x: f64) -> f64;\n    fn hypot(x: f64, y: f64) -> f64;\n    fn crc32_bytes(s: ByteSlice) -> u32;\n    fn stats_of(xs: I32Slice, out: *mut Stats);\n    fn c_version(out: GooseBuilder);\n}\n",
      "rust_context_url": "rust/057.rs",
      "rust_support_urls": [],
      "semantic_note": "FFI declaration adapter only: Stats needs its real definition and all descriptors must match the generated C header/target ABI. Goose's builder is a header/stack descriptor passed by value, not a Rust Vec reference. No C implementation is linked or exercised here.",
      "relationship": "ffi_declaration_adapter",
      "validation": {
        "kind": "compile_only_external_context",
        "status": "pass",
        "context_note": "Compile-only Rust metadata check. Stats is opaque; there are no native package downloads or fabricated C implementations. Calling these declarations needs the actual matching external context."
      },
      "goose_sha256": "000ecac43ed4f475bd2d730cb36aaaa3b347c4e4cc9a9b882f5a3d292354e97b",
      "rust_sha256": "ea2481eec36159cb17fa8b84bf5d3ccaf38753510766088a682d6ea3ca5829f5"
    },
    {
      "ordinal": 58,
      "anchor": "example-58",
      "original_heading": "## 17. About the speed",
      "original_line": 1525,
      "goose": "let W = 512;\n\n// Each row of the image is a slice; the caller passes three source rows and\n// one destination row per output row.\nfn blur_row(above: u8[:], here: u8[:], below: u8[:], out: u8[:]) {\n    assert(above.len == W && here.len == W && below.len == W && out.len == W);\n    for x in 1..W - 1 {\n        let sum = above[x - 1] as i64 + above[x] + above[x + 1] +\n                  here[x - 1]  + here[x]  + here[x + 1] +\n                  below[x - 1] + below[x] + below[x + 1];\n        out[x] = (sum / 9) as! u8;\n    }\n}\n",
      "rust": "const W: usize = 512;\nfn blur_row(above: &[u8], here: &[u8], below: &[u8], out: &mut [u8]) {\n    assert!(above.len() == W && here.len() == W && below.len() == W && out.len() == W);\n    for x in 1..W - 1 {\n        let sum = i64::from(above[x - 1]) + i64::from(above[x]) + i64::from(above[x + 1]) +\n                  i64::from(here[x - 1])  + i64::from(here[x])  + i64::from(here[x + 1]) +\n                  i64::from(below[x - 1]) + i64::from(below[x]) + i64::from(below[x + 1]);\n        out[x] = u8::try_from(sum / 9).unwrap();\n    }\n}\n",
      "rust_context_url": "rust/058.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust explicitly widens all nine operands. The average is always 0..=255, so the checked narrowing succeeds. Rust requires an exclusive output slice; this signature does not permit overlapping input/output aliases. No Rust bounds-check-elimination result is asserted.",
      "relationship": "behavior",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": null
      },
      "goose_sha256": "8a4173876908c11233d101de606ae29e7b9bdf98a6fcdcd5a224021e3da71af1",
      "rust_sha256": "5afa27e72f92ab9769b947c578990ad665edab60aec7b0f97fb16c1d173759a2"
    },
    {
      "ordinal": 59,
      "anchor": "example-59",
      "original_heading": "## 19. Calling Goose from C",
      "original_line": 1635,
      "goose": "var calls: i32 = 0;\n\nexport fn hello_world() -> const u8[:] {\n    calls += 1;\n    return \"Hello, world!\"\n}\n\nexport \"c_add\" fn add(a: i32, b: i32) -> i32 { a + b }\n\nfn main() {\n    calls = 100;    // runs once, inside goose_init\n}\n",
      "rust": "use std::cell::Cell;\nuse std::ffi::c_char;\nthread_local! { static CALLS: Cell<i32> = const { Cell::new(0) }; }\n#[unsafe(no_mangle)]\npub extern \"C\" fn goose_init(_argc: i32, _argv: *mut *mut c_char) {\n    CALLS.with(|calls| calls.set(100)); // this example's startup state only\n}\n/// Safety: length must point to a live, writable, aligned i64.\n#[unsafe(no_mangle)]\npub unsafe extern \"C\" fn hello_world(length: *mut i64) -> *const u8 {\n    CALLS.with(|calls| calls.set(calls.get() + 1));\n    const MESSAGE: &[u8] = b\"Hello, world!\";\n    unsafe { *length = MESSAGE.len() as i64; }\n    MESSAGE.as_ptr() // static bytes, not NUL-terminated\n}\n#[unsafe(export_name = \"c_add\")]\npub extern \"C\" fn add(a: i32, b: i32) -> i32 { a + b }\n",
      "rust_context_url": "rust/059.rs",
      "rust_support_urls": [],
      "semantic_note": "Rust spells the C ABI, exported symbols and pointer-length result explicitly. This goose_init only initializes this example's Rust state; it is not a replacement for the Goose runtime. Calls follow the original same-thread contract.",
      "relationship": "ffi_export_adapter",
      "validation": {
        "kind": "run",
        "status": "pass",
        "context_note": "Harness imitates the adjacent C caller with Rust C-ABI calls; it does not link Goose-generated C. The one unsafe pointer write/read is confined to this explicit FFI boundary."
      },
      "goose_sha256": "a5a970fbcfb0910021763b6e8a370f421b0618283e90973be63bc265c8d8ba64",
      "rust_sha256": "5c0a9b13da0c94355899a0a6658aff323699bf9b0e658a96db620d0f110da91d"
    }
  ]
}
