1package util
2
3import (
4 "bytes"
5 "math"
6
7 "github.com/tetratelabs/wazero/api"
8)
9
10const (
11 PtrLen = 4
12 IntLen = 4
13)
14
15type (
16 i8 interface{ ~int8 | ~uint8 }
17 i32 interface{ ~int32 | ~uint32 }
18 i64 interface{ ~int64 | ~uint64 }
19
20 Stk_t = uint64
21 Ptr_t uint32
22 Res_t int32
23)
24
25func View(mod api.Module, ptr Ptr_t, size int64) []byte {
26 if ptr == 0 {
27 panic(NilErr)
28 }
29 if uint64(size) > math.MaxUint32 {
30 panic(RangeErr)
31 }
32 buf, ok := mod.Memory().Read(uint32(ptr), uint32(size))
33 if !ok {
34 panic(RangeErr)
35 }
36 return buf
37}
38
39func Read[T i8](mod api.Module, ptr Ptr_t) T {
40 if ptr == 0 {
41 panic(NilErr)
42 }
43 v, ok := mod.Memory().ReadByte(uint32(ptr))
44 if !ok {
45 panic(RangeErr)
46 }
47 return T(v)
48}
49
50func Write[T i8](mod api.Module, ptr Ptr_t, v T) {
51 if ptr == 0 {
52 panic(NilErr)
53 }
54 ok := mod.Memory().WriteByte(uint32(ptr), uint8(v))
55 if !ok {
56 panic(RangeErr)
57 }
58}
59
60func Read32[T i32](mod api.Module, ptr Ptr_t) T {
61 if ptr == 0 {
62 panic(NilErr)
63 }
64 v, ok := mod.Memory().ReadUint32Le(uint32(ptr))
65 if !ok {
66 panic(RangeErr)
67 }
68 return T(v)
69}
70
71func Write32[T i32](mod api.Module, ptr Ptr_t, v T) {
72 if ptr == 0 {
73 panic(NilErr)
74 }
75 ok := mod.Memory().WriteUint32Le(uint32(ptr), uint32(v))
76 if !ok {
77 panic(RangeErr)
78 }
79}
80
81func Read64[T i64](mod api.Module, ptr Ptr_t) T {
82 if ptr == 0 {
83 panic(NilErr)
84 }
85 v, ok := mod.Memory().ReadUint64Le(uint32(ptr))
86 if !ok {
87 panic(RangeErr)
88 }
89 return T(v)
90}
91
92func Write64[T i64](mod api.Module, ptr Ptr_t, v T) {
93 if ptr == 0 {
94 panic(NilErr)
95 }
96 ok := mod.Memory().WriteUint64Le(uint32(ptr), uint64(v))
97 if !ok {
98 panic(RangeErr)
99 }
100}
101
102func ReadFloat64(mod api.Module, ptr Ptr_t) float64 {
103 return math.Float64frombits(Read64[uint64](mod, ptr))
104}
105
106func WriteFloat64(mod api.Module, ptr Ptr_t, v float64) {
107 Write64(mod, ptr, math.Float64bits(v))
108}
109
110func ReadBool(mod api.Module, ptr Ptr_t) bool {
111 return Read32[int32](mod, ptr) != 0
112}
113
114func WriteBool(mod api.Module, ptr Ptr_t, v bool) {
115 var i int32
116 if v {
117 i = 1
118 }
119 Write32(mod, ptr, i)
120}
121
122func ReadString(mod api.Module, ptr Ptr_t, maxlen int64) string {
123 if ptr == 0 {
124 panic(NilErr)
125 }
126 if maxlen <= 0 {
127 return ""
128 }
129 mem := mod.Memory()
130 maxlen = min(maxlen, math.MaxInt32-1) + 1
131 buf, ok := mem.Read(uint32(ptr), uint32(maxlen))
132 if !ok {
133 buf, ok = mem.Read(uint32(ptr), mem.Size()-uint32(ptr))
134 if !ok {
135 panic(RangeErr)
136 }
137 }
138 if i := bytes.IndexByte(buf, 0); i >= 0 {
139 return string(buf[:i])
140 }
141 panic(NoNulErr)
142}
143
144func WriteBytes(mod api.Module, ptr Ptr_t, b []byte) {
145 buf := View(mod, ptr, int64(len(b)))
146 copy(buf, b)
147}
148
149func WriteString(mod api.Module, ptr Ptr_t, s string) {
150 buf := View(mod, ptr, int64(len(s))+1)
151 buf[len(s)] = 0
152 copy(buf, s)
153}