diff options
Diffstat (limited to 'vendor/codeberg.org/gruf/go-ffmpreg/util')
-rw-r--r-- | vendor/codeberg.org/gruf/go-ffmpreg/util/funcs.go | 65 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-ffmpreg/util/wasm.go | 81 |
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 +} |