main.go raw
1 // Trivial test organ: echoes input back with a prefix.
2 // Built with: GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o trivial.wasm .
3 package main
4
5 import "unsafe"
6
7 // Memory pool: a simple bump allocator for guest-side allocations.
8 // This avoids Go GC issues in WASM by using a fixed buffer.
9 var pool [1 << 20]byte // 1MB
10 var poolOffset uint32
11
12 //go:wasmexport alloc
13 func alloc(size uint32) uint32 {
14 if poolOffset+size > uint32(len(pool)) {
15 // Reset if exhausted (simple strategy for short-lived calls).
16 poolOffset = 0
17 }
18 ptr := poolOffset
19 poolOffset += size
20 return uint32(uintptr(unsafe.Pointer(&pool[ptr])))
21 }
22
23 //go:wasmexport dealloc
24 func dealloc(ptr uint32, size uint32) {
25 // No-op with bump allocator. Memory is reclaimed on pool reset.
26 }
27
28 //go:wasmexport organ_type
29 func organ_type() uint32 {
30 s := "enzyme"
31 ptr := alloc(uint32(len(s)))
32 copy(pool[ptr-uint32(uintptr(unsafe.Pointer(&pool[0]))):], s)
33 return ptr
34 }
35
36 //go:wasmexport organ_version
37 func organ_version() uint64 {
38 return 1
39 }
40
41 //go:wasmexport process
42 func process(inputPtr uint32, inputLen uint32) uint64 {
43 // Read input from our pool by computing offset.
44 base := uint32(uintptr(unsafe.Pointer(&pool[0])))
45 offset := inputPtr - base
46
47 if offset+inputLen > uint32(len(pool)) {
48 // Out of bounds — return empty.
49 return 0
50 }
51
52 input := pool[offset : offset+inputLen]
53
54 if len(input) == 0 {
55 return 0
56 }
57
58 opcode := input[0]
59 data := input[1:]
60
61 var result []byte
62
63 switch opcode {
64 case 0x01: // CanDigest: return 0x01 if input contains "package "
65 result = []byte{0x00}
66 for i := 0; i+8 <= len(data); i++ {
67 if string(data[i:i+8]) == "package " {
68 result = []byte{0x01}
69 break
70 }
71 }
72
73 case 0x02: // Digest: return the input prefixed with "digested:"
74 prefix := []byte("digested:")
75 result = make([]byte, len(prefix)+len(data))
76 copy(result, prefix)
77 copy(result[len(prefix):], data)
78
79 default:
80 result = []byte("unknown opcode")
81 }
82
83 // Write result to pool.
84 outPtr := alloc(uint32(len(result)))
85 outOffset := outPtr - base
86 copy(pool[outOffset:], result)
87
88 // Pack pointer and length into uint64.
89 return uint64(outPtr)<<32 | uint64(len(result))
90 }
91
92 func main() {}
93