notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

build_hello_wasm.rs (5124B)


      1 /// Compiles the hello WAT module to a .wasm file and places it in
      2 /// the notedeck wasm_apps directory for testing.
      3 ///
      4 /// Usage: cargo run -p notedeck_wasm --example build_hello_wasm
      5 fn main() {
      6     let wat = r#"(module
      7         (import "env" "nd_heading" (func $nd_heading (param i32 i32)))
      8         (import "env" "nd_label"   (func $nd_label   (param i32 i32)))
      9         (import "env" "nd_button"  (func $nd_button   (param i32 i32) (result i32)))
     10         (import "env" "nd_add_space" (func $nd_add_space (param f32)))
     11 
     12         (memory (export "memory") 1)
     13 
     14         ;; Static strings
     15         (data (i32.const 0)  "Hello from WASM!")   ;; 16 bytes
     16         (data (i32.const 16) "Click me")           ;; 8 bytes
     17         (data (i32.const 24) "Clicks: ")           ;; 8 bytes
     18         (data (i32.const 32) "0123456789")         ;; digit table
     19 
     20         ;; App metadata
     21         (data (i32.const 500) "Hello WASM")
     22         (global (export "nd_app_name_ptr") i32 (i32.const 500))
     23         (global (export "nd_app_name_len") i32 (i32.const 10))
     24 
     25         ;; Global click counter
     26         (global $count (mut i32) (i32.const 0))
     27 
     28         ;; Simple itoa: writes decimal digits at ptr, returns length
     29         (func $itoa (param $n i32) (param $ptr i32) (result i32)
     30             (local $len i32)
     31             (local $tmp i32)
     32             (local $start i32)
     33             (local $end i32)
     34             (local $swap i32)
     35 
     36             ;; Handle zero
     37             (if (i32.eqz (local.get $n))
     38                 (then
     39                     (i32.store8 (local.get $ptr) (i32.const 48)) ;; '0'
     40                     (return (i32.const 1))
     41                 )
     42             )
     43 
     44             ;; Write digits in reverse
     45             (local.set $tmp (local.get $n))
     46             (local.set $len (i32.const 0))
     47             (block $done
     48                 (loop $digits
     49                     (br_if $done (i32.eqz (local.get $tmp)))
     50                     (i32.store8
     51                         (i32.add (local.get $ptr) (local.get $len))
     52                         (i32.add (i32.const 48)
     53                             (i32.rem_u (local.get $tmp) (i32.const 10))))
     54                     (local.set $tmp (i32.div_u (local.get $tmp) (i32.const 10)))
     55                     (local.set $len (i32.add (local.get $len) (i32.const 1)))
     56                     (br $digits)
     57                 )
     58             )
     59 
     60             ;; Reverse the digits in place
     61             (local.set $start (i32.const 0))
     62             (local.set $end (i32.sub (local.get $len) (i32.const 1)))
     63             (block $rev_done
     64                 (loop $rev
     65                     (br_if $rev_done (i32.ge_u (local.get $start) (local.get $end)))
     66                     ;; swap
     67                     (local.set $swap
     68                         (i32.load8_u (i32.add (local.get $ptr) (local.get $start))))
     69                     (i32.store8
     70                         (i32.add (local.get $ptr) (local.get $start))
     71                         (i32.load8_u (i32.add (local.get $ptr) (local.get $end))))
     72                     (i32.store8
     73                         (i32.add (local.get $ptr) (local.get $end))
     74                         (local.get $swap))
     75                     (local.set $start (i32.add (local.get $start) (i32.const 1)))
     76                     (local.set $end (i32.sub (local.get $end) (i32.const 1)))
     77                     (br $rev)
     78                 )
     79             )
     80 
     81             (local.get $len)
     82         )
     83 
     84         (func (export "nd_update")
     85             (local $num_len i32)
     86 
     87             ;; Heading
     88             (call $nd_heading (i32.const 0) (i32.const 16))
     89             (call $nd_add_space (f32.const 8.0))
     90 
     91             ;; Button
     92             (if (call $nd_button (i32.const 16) (i32.const 8))
     93                 (then
     94                     (global.set $count
     95                         (i32.add (global.get $count) (i32.const 1)))
     96                 )
     97             )
     98             (call $nd_add_space (f32.const 4.0))
     99 
    100             ;; "Clicks: " prefix is at offset 24 (8 bytes)
    101             ;; Write the number starting at offset 100 (scratch space)
    102             (local.set $num_len
    103                 (call $itoa (global.get $count) (i32.const 100)))
    104 
    105             ;; Copy "Clicks: " to offset 200, then append the number
    106             ;; offset 200: "Clicks: "
    107             (memory.copy (i32.const 200) (i32.const 24) (i32.const 8))
    108             ;; offset 208: number digits
    109             (memory.copy
    110                 (i32.const 208)
    111                 (i32.const 100)
    112                 (local.get $num_len))
    113 
    114             ;; Label with total length = 8 + num_len
    115             (call $nd_label
    116                 (i32.const 200)
    117                 (i32.add (i32.const 8) (local.get $num_len)))
    118         )
    119     )"#;
    120 
    121     let wasm = wat::parse_str(wat).expect("failed to parse WAT");
    122 
    123     // Write to the notedeck wasm_apps directory
    124     let dir = dirs::data_dir()
    125         .expect("data dir")
    126         .join("notedeck")
    127         .join("cache")
    128         .join("wasm_apps");
    129     std::fs::create_dir_all(&dir).expect("create wasm_apps dir");
    130 
    131     let path = dir.join("hello.wasm");
    132     std::fs::write(&path, &wasm).expect("write hello.wasm");
    133     println!("Wrote {} bytes to {}", wasm.len(), path.display());
    134 }