summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-ffmpreg/util
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/codeberg.org/gruf/go-ffmpreg/util')
-rw-r--r--vendor/codeberg.org/gruf/go-ffmpreg/util/funcs.go65
-rw-r--r--vendor/codeberg.org/gruf/go-ffmpreg/util/wasm.go81
2 files changed, 146 insertions, 0 deletions
diff --git a/vendor/codeberg.org/gruf/go-ffmpreg/util/funcs.go b/vendor/codeberg.org/gruf/go-ffmpreg/util/funcs.go
new file mode 100644
index 000000000..4b584cf41
--- /dev/null
+++ b/vendor/codeberg.org/gruf/go-ffmpreg/util/funcs.go
@@ -0,0 +1,65 @@
+package util
+
+import (
+ "context"
+ "os"
+ "path"
+ "strconv"
+ "time"
+
+ "github.com/tetratelabs/wazero/api"
+)
+
+// Wasm_Tempnam wraps Go_Tempnam to fulfill wazero's api.GoModuleFunc,
+// the argument definition is (i32, i32) and return definition is (i32).
+// NOTE: the calling module MUST have access to exported malloc / free.
+func Wasm_Tempnam(ctx context.Context, mod api.Module, stack []uint64) {
+ dirptr := api.DecodeU32(stack[0])
+ pfxptr := api.DecodeU32(stack[1])
+ dir := readString(ctx, mod, dirptr, 0)
+ pfx := readString(ctx, mod, pfxptr, 0)
+ tmpstr := Go_Tempnam(dir, pfx)
+ tmpptr := writeString(ctx, mod, tmpstr)
+ stack[0] = api.EncodeU32(tmpptr)
+}
+
+// Go_Tempname is functionally similar to C's tempnam.
+func Go_Tempnam(dir, prefix string) string {
+ now := time.Now().Unix()
+ prefix = path.Join(dir, prefix)
+ for i := 0; i < 1000; i++ {
+ n := murmur2(uint32(now + int64(i)))
+ name := prefix + strconv.FormatUint(uint64(n), 10)
+ _, err := os.Stat(name)
+ if err == nil {
+ continue
+ } else if os.IsNotExist(err) {
+ return name
+ } else {
+ panic(err)
+ }
+ }
+ panic("too many attempts")
+}
+
+// murmur2 is a simple uint32 murmur2 hash
+// impl with fixed seed and input size.
+func murmur2(k uint32) (h uint32) {
+ const (
+ // seed ^ bitlen
+ s = uint32(2147483647) ^ 8
+
+ M = 0x5bd1e995
+ R = 24
+ )
+ h = s
+ k *= M
+ k ^= k >> R
+ k *= M
+ h *= M
+ h ^= k
+ h ^= h >> 13
+ h *= M
+ h ^= h >> 15
+ return
+}
diff --git a/vendor/codeberg.org/gruf/go-ffmpreg/util/wasm.go b/vendor/codeberg.org/gruf/go-ffmpreg/util/wasm.go
new file mode 100644
index 000000000..fce41d0a0
--- /dev/null
+++ b/vendor/codeberg.org/gruf/go-ffmpreg/util/wasm.go
@@ -0,0 +1,81 @@
+package util
+
+import (
+ "bytes"
+ "context"
+
+ "github.com/tetratelabs/wazero/api"
+)
+
+// NOTE:
+// the below functions are not very well optimized
+// for repeated calls. this is relying on the fact
+// that the only place they get used (tempnam), is
+// not called very often, should only be once per run
+// so calls to ExportedFunction() and Call() instead
+// of caching api.Function and using CallWithStack()
+// will work out the same (if only called once).
+
+// maxaddr is the maximum
+// wasm32 memory address.
+const maxaddr = ^uint32(0)
+
+func malloc(ctx context.Context, mod api.Module, sz uint32) uint32 {
+ stack, err := mod.ExportedFunction("malloc").Call(ctx, uint64(sz))
+ if err != nil {
+ panic(err)
+ }
+ ptr := api.DecodeU32(stack[0])
+ if ptr == 0 {
+ panic("out of memory")
+ }
+ return ptr
+}
+
+func free(ctx context.Context, mod api.Module, ptr uint32) {
+ if ptr != 0 {
+ mod.ExportedFunction("free").Call(ctx, uint64(ptr))
+ }
+}
+
+func view(ctx context.Context, mod api.Module, ptr uint32, n uint32) []byte {
+ if n == 0 {
+ n = maxaddr - ptr
+ }
+ mem := mod.Memory()
+ b, ok := mem.Read(ptr, n)
+ if !ok {
+ panic("out of range")
+ }
+ return b
+}
+
+func read(ctx context.Context, mod api.Module, ptr, n uint32) []byte {
+ return bytes.Clone(view(ctx, mod, ptr, n))
+}
+
+func readString(ctx context.Context, mod api.Module, ptr, n uint32) string {
+ return string(view(ctx, mod, ptr, n))
+}
+
+func write(ctx context.Context, mod api.Module, b []byte) uint32 {
+ mem := mod.Memory()
+ len := uint32(len(b))
+ ptr := malloc(ctx, mod, len)
+ ok := mem.Write(ptr, b)
+ if !ok {
+ panic("out of range")
+ }
+ return ptr
+}
+
+func writeString(ctx context.Context, mod api.Module, str string) uint32 {
+ mem := mod.Memory()
+ len := uint32(len(str) + 1)
+ ptr := malloc(ctx, mod, len)
+ ok := mem.WriteString(ptr, str)
+ if !ok {
+ panic("out of range")
+ }
+ return ptr
+}