diff options
| author | 2024-05-27 15:46:15 +0000 | |
|---|---|---|
| committer | 2024-05-27 17:46:15 +0200 | |
| commit | 1e7b32490dfdccddd04f46d4b0416b48d749d51b (patch) | |
| tree | 62a11365933a5a11e0800af64cbdf9172e5e6e7a /vendor/github.com/ncruces/go-sqlite3/internal/util | |
| parent | [chore] Small styling + link issues (#2933) (diff) | |
| download | gotosocial-1e7b32490dfdccddd04f46d4b0416b48d749d51b.tar.xz | |
[experiment] add alternative wasm sqlite3 implementation available via build-tag (#2863)
This allows for building GoToSocial with [SQLite transpiled to WASM](https://github.com/ncruces/go-sqlite3) and accessed through [Wazero](https://wazero.io/).
Diffstat (limited to 'vendor/github.com/ncruces/go-sqlite3/internal/util')
16 files changed, 1009 insertions, 0 deletions
| diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/alloc_other.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/alloc_other.go new file mode 100644 index 000000000..ba16efc02 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/alloc_other.go @@ -0,0 +1,9 @@ +//go:build !(unix || windows) || sqlite3_nosys + +package util + +import "github.com/tetratelabs/wazero/experimental" + +func virtualAlloc(cap, max uint64) experimental.LinearMemory { +	return sliceAlloc(cap, max) +} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/alloc_slice.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/alloc_slice.go new file mode 100644 index 000000000..b8cc1453c --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/alloc_slice.go @@ -0,0 +1,25 @@ +//go:build !(darwin || linux) || !(amd64 || arm64 || riscv64) || sqlite3_noshm || sqlite3_nosys + +package util + +import "github.com/tetratelabs/wazero/experimental" + +func sliceAlloc(cap, max uint64) experimental.LinearMemory { +	return &sliceBuffer{make([]byte, cap), max} +} + +type sliceBuffer struct { +	buf []byte +	max uint64 +} + +func (b *sliceBuffer) Free() {} + +func (b *sliceBuffer) Reallocate(size uint64) []byte { +	if cap := uint64(cap(b.buf)); size > cap { +		b.buf = append(b.buf[:cap], make([]byte, size-cap)...) +	} else { +		b.buf = b.buf[:size] +	} +	return b.buf +} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/alloc_unix.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/alloc_unix.go new file mode 100644 index 000000000..2b1d3916b --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/alloc_unix.go @@ -0,0 +1,67 @@ +//go:build unix && !sqlite3_nosys + +package util + +import ( +	"math" + +	"github.com/tetratelabs/wazero/experimental" +	"golang.org/x/sys/unix" +) + +func virtualAlloc(cap, max uint64) experimental.LinearMemory { +	// Round up to the page size. +	rnd := uint64(unix.Getpagesize() - 1) +	max = (max + rnd) &^ rnd + +	if max > math.MaxInt { +		// This ensures int(max) overflows to a negative value, +		// and unix.Mmap returns EINVAL. +		max = math.MaxUint64 +	} + +	// Reserve max bytes of address space, to ensure we won't need to move it. +	// A protected, private, anonymous mapping should not commit memory. +	b, err := unix.Mmap(-1, 0, int(max), unix.PROT_NONE, unix.MAP_PRIVATE|unix.MAP_ANON) +	if err != nil { +		panic(err) +	} +	return &mmappedMemory{buf: b[:0]} +} + +// The slice covers the entire mmapped memory: +//   - len(buf) is the already committed memory, +//   - cap(buf) is the reserved address space. +type mmappedMemory struct { +	buf []byte +} + +func (m *mmappedMemory) Reallocate(size uint64) []byte { +	com := uint64(len(m.buf)) +	res := uint64(cap(m.buf)) +	if com < size && size < res { +		// Round up to the page size. +		rnd := uint64(unix.Getpagesize() - 1) +		new := (size + rnd) &^ rnd + +		// Commit additional memory up to new bytes. +		err := unix.Mprotect(m.buf[com:new], unix.PROT_READ|unix.PROT_WRITE) +		if err != nil { +			panic(err) +		} + +		// Update committed memory. +		m.buf = m.buf[:new] +	} +	// Limit returned capacity because bytes beyond +	// len(m.buf) have not yet been committed. +	return m.buf[:size:len(m.buf)] +} + +func (m *mmappedMemory) Free() { +	err := unix.Munmap(m.buf[:cap(m.buf)]) +	if err != nil { +		panic(err) +	} +	m.buf = nil +} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/alloc_windows.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/alloc_windows.go new file mode 100644 index 000000000..8936173b4 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/alloc_windows.go @@ -0,0 +1,76 @@ +//go:build !sqlite3_nosys + +package util + +import ( +	"math" +	"reflect" +	"unsafe" + +	"github.com/tetratelabs/wazero/experimental" +	"golang.org/x/sys/windows" +) + +func virtualAlloc(cap, max uint64) experimental.LinearMemory { +	// Round up to the page size. +	rnd := uint64(windows.Getpagesize() - 1) +	max = (max + rnd) &^ rnd + +	if max > math.MaxInt { +		// This ensures uintptr(max) overflows to a large value, +		// and windows.VirtualAlloc returns an error. +		max = math.MaxUint64 +	} + +	// Reserve max bytes of address space, to ensure we won't need to move it. +	// This does not commit memory. +	r, err := windows.VirtualAlloc(0, uintptr(max), windows.MEM_RESERVE, windows.PAGE_READWRITE) +	if err != nil { +		panic(err) +	} + +	mem := virtualMemory{addr: r} +	// SliceHeader, although deprecated, avoids a go vet warning. +	sh := (*reflect.SliceHeader)(unsafe.Pointer(&mem.buf)) +	sh.Cap = int(max) // Not a bug. +	sh.Data = r +	return &mem +} + +// The slice covers the entire mmapped memory: +//   - len(buf) is the already committed memory, +//   - cap(buf) is the reserved address space. +type virtualMemory struct { +	buf  []byte +	addr uintptr +} + +func (m *virtualMemory) Reallocate(size uint64) []byte { +	com := uint64(len(m.buf)) +	res := uint64(cap(m.buf)) +	if com < size && size < res { +		// Round up to the page size. +		rnd := uint64(windows.Getpagesize() - 1) +		new := (size + rnd) &^ rnd + +		// Commit additional memory up to new bytes. +		_, err := windows.VirtualAlloc(m.addr, uintptr(new), windows.MEM_COMMIT, windows.PAGE_READWRITE) +		if err != nil { +			panic(err) +		} + +		// Update committed memory. +		m.buf = m.buf[:new] +	} +	// Limit returned capacity because bytes beyond +	// len(m.buf) have not yet been committed. +	return m.buf[:size:len(m.buf)] +} + +func (m *virtualMemory) Free() { +	err := windows.VirtualFree(m.addr, 0, windows.MEM_RELEASE) +	if err != nil { +		panic(err) +	} +	m.addr = 0 +} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/bool.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/bool.go new file mode 100644 index 000000000..8427f3085 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/bool.go @@ -0,0 +1,22 @@ +package util + +import "strings" + +func ParseBool(s string) (b, ok bool) { +	if len(s) == 0 { +		return false, false +	} +	if s[0] == '0' { +		return false, true +	} +	if '1' <= s[0] && s[0] <= '9' { +		return true, true +	} +	switch strings.ToLower(s) { +	case "true", "yes", "on": +		return true, true +	case "false", "no", "off": +		return false, true +	} +	return false, false +} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/const.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/const.go new file mode 100644 index 000000000..86bb9749d --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/const.go @@ -0,0 +1,117 @@ +package util + +// https://sqlite.com/matrix/rescode.html +const ( +	OK = 0 /* Successful result */ + +	ERROR      = 1  /* Generic error */ +	INTERNAL   = 2  /* Internal logic error in SQLite */ +	PERM       = 3  /* Access permission denied */ +	ABORT      = 4  /* Callback routine requested an abort */ +	BUSY       = 5  /* The database file is locked */ +	LOCKED     = 6  /* A table in the database is locked */ +	NOMEM      = 7  /* A malloc() failed */ +	READONLY   = 8  /* Attempt to write a readonly database */ +	INTERRUPT  = 9  /* Operation terminated by sqlite3_interrupt() */ +	IOERR      = 10 /* Some kind of disk I/O error occurred */ +	CORRUPT    = 11 /* The database disk image is malformed */ +	NOTFOUND   = 12 /* Unknown opcode in sqlite3_file_control() */ +	FULL       = 13 /* Insertion failed because database is full */ +	CANTOPEN   = 14 /* Unable to open the database file */ +	PROTOCOL   = 15 /* Database lock protocol error */ +	EMPTY      = 16 /* Internal use only */ +	SCHEMA     = 17 /* The database schema changed */ +	TOOBIG     = 18 /* String or BLOB exceeds size limit */ +	CONSTRAINT = 19 /* Abort due to constraint violation */ +	MISMATCH   = 20 /* Data type mismatch */ +	MISUSE     = 21 /* Library used incorrectly */ +	NOLFS      = 22 /* Uses OS features not supported on host */ +	AUTH       = 23 /* Authorization denied */ +	FORMAT     = 24 /* Not used */ +	RANGE      = 25 /* 2nd parameter to sqlite3_bind out of range */ +	NOTADB     = 26 /* File opened that is not a database file */ +	NOTICE     = 27 /* Notifications from sqlite3_log() */ +	WARNING    = 28 /* Warnings from sqlite3_log() */ + +	ROW  = 100 /* sqlite3_step() has another row ready */ +	DONE = 101 /* sqlite3_step() has finished executing */ + +	ERROR_MISSING_COLLSEQ   = ERROR | (1 << 8) +	ERROR_RETRY             = ERROR | (2 << 8) +	ERROR_SNAPSHOT          = ERROR | (3 << 8) +	IOERR_READ              = IOERR | (1 << 8) +	IOERR_SHORT_READ        = IOERR | (2 << 8) +	IOERR_WRITE             = IOERR | (3 << 8) +	IOERR_FSYNC             = IOERR | (4 << 8) +	IOERR_DIR_FSYNC         = IOERR | (5 << 8) +	IOERR_TRUNCATE          = IOERR | (6 << 8) +	IOERR_FSTAT             = IOERR | (7 << 8) +	IOERR_UNLOCK            = IOERR | (8 << 8) +	IOERR_RDLOCK            = IOERR | (9 << 8) +	IOERR_DELETE            = IOERR | (10 << 8) +	IOERR_BLOCKED           = IOERR | (11 << 8) +	IOERR_NOMEM             = IOERR | (12 << 8) +	IOERR_ACCESS            = IOERR | (13 << 8) +	IOERR_CHECKRESERVEDLOCK = IOERR | (14 << 8) +	IOERR_LOCK              = IOERR | (15 << 8) +	IOERR_CLOSE             = IOERR | (16 << 8) +	IOERR_DIR_CLOSE         = IOERR | (17 << 8) +	IOERR_SHMOPEN           = IOERR | (18 << 8) +	IOERR_SHMSIZE           = IOERR | (19 << 8) +	IOERR_SHMLOCK           = IOERR | (20 << 8) +	IOERR_SHMMAP            = IOERR | (21 << 8) +	IOERR_SEEK              = IOERR | (22 << 8) +	IOERR_DELETE_NOENT      = IOERR | (23 << 8) +	IOERR_MMAP              = IOERR | (24 << 8) +	IOERR_GETTEMPPATH       = IOERR | (25 << 8) +	IOERR_CONVPATH          = IOERR | (26 << 8) +	IOERR_VNODE             = IOERR | (27 << 8) +	IOERR_AUTH              = IOERR | (28 << 8) +	IOERR_BEGIN_ATOMIC      = IOERR | (29 << 8) +	IOERR_COMMIT_ATOMIC     = IOERR | (30 << 8) +	IOERR_ROLLBACK_ATOMIC   = IOERR | (31 << 8) +	IOERR_DATA              = IOERR | (32 << 8) +	IOERR_CORRUPTFS         = IOERR | (33 << 8) +	IOERR_IN_PAGE           = IOERR | (34 << 8) +	LOCKED_SHAREDCACHE      = LOCKED | (1 << 8) +	LOCKED_VTAB             = LOCKED | (2 << 8) +	BUSY_RECOVERY           = BUSY | (1 << 8) +	BUSY_SNAPSHOT           = BUSY | (2 << 8) +	BUSY_TIMEOUT            = BUSY | (3 << 8) +	CANTOPEN_NOTEMPDIR      = CANTOPEN | (1 << 8) +	CANTOPEN_ISDIR          = CANTOPEN | (2 << 8) +	CANTOPEN_FULLPATH       = CANTOPEN | (3 << 8) +	CANTOPEN_CONVPATH       = CANTOPEN | (4 << 8) +	CANTOPEN_DIRTYWAL       = CANTOPEN | (5 << 8) /* Not Used */ +	CANTOPEN_SYMLINK        = CANTOPEN | (6 << 8) +	CORRUPT_VTAB            = CORRUPT | (1 << 8) +	CORRUPT_SEQUENCE        = CORRUPT | (2 << 8) +	CORRUPT_INDEX           = CORRUPT | (3 << 8) +	READONLY_RECOVERY       = READONLY | (1 << 8) +	READONLY_CANTLOCK       = READONLY | (2 << 8) +	READONLY_ROLLBACK       = READONLY | (3 << 8) +	READONLY_DBMOVED        = READONLY | (4 << 8) +	READONLY_CANTINIT       = READONLY | (5 << 8) +	READONLY_DIRECTORY      = READONLY | (6 << 8) +	ABORT_ROLLBACK          = ABORT | (2 << 8) +	CONSTRAINT_CHECK        = CONSTRAINT | (1 << 8) +	CONSTRAINT_COMMITHOOK   = CONSTRAINT | (2 << 8) +	CONSTRAINT_FOREIGNKEY   = CONSTRAINT | (3 << 8) +	CONSTRAINT_FUNCTION     = CONSTRAINT | (4 << 8) +	CONSTRAINT_NOTNULL      = CONSTRAINT | (5 << 8) +	CONSTRAINT_PRIMARYKEY   = CONSTRAINT | (6 << 8) +	CONSTRAINT_TRIGGER      = CONSTRAINT | (7 << 8) +	CONSTRAINT_UNIQUE       = CONSTRAINT | (8 << 8) +	CONSTRAINT_VTAB         = CONSTRAINT | (9 << 8) +	CONSTRAINT_ROWID        = CONSTRAINT | (10 << 8) +	CONSTRAINT_PINNED       = CONSTRAINT | (11 << 8) +	CONSTRAINT_DATATYPE     = CONSTRAINT | (12 << 8) +	NOTICE_RECOVER_WAL      = NOTICE | (1 << 8) +	NOTICE_RECOVER_ROLLBACK = NOTICE | (2 << 8) +	NOTICE_RBU              = NOTICE | (3 << 8) +	WARNING_AUTOINDEX       = WARNING | (1 << 8) +	AUTH_USER               = AUTH | (1 << 8) + +	OK_LOAD_PERMANENTLY = OK | (1 << 8) +	OK_SYMLINK          = OK | (2 << 8) /* internal use only */ +) diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/error.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/error.go new file mode 100644 index 000000000..1f5555fd3 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/error.go @@ -0,0 +1,106 @@ +package util + +import ( +	"runtime" +	"strconv" +) + +type ErrorString string + +func (e ErrorString) Error() string { return string(e) } + +const ( +	NilErr       = ErrorString("sqlite3: invalid memory address or null pointer dereference") +	OOMErr       = ErrorString("sqlite3: out of memory") +	RangeErr     = ErrorString("sqlite3: index out of range") +	NoNulErr     = ErrorString("sqlite3: missing NUL terminator") +	NoBinaryErr  = ErrorString("sqlite3: no SQLite binary embed/set/loaded") +	BadBinaryErr = ErrorString("sqlite3: invalid SQLite binary embed/set/loaded") +	TimeErr      = ErrorString("sqlite3: invalid time value") +	WhenceErr    = ErrorString("sqlite3: invalid whence") +	OffsetErr    = ErrorString("sqlite3: invalid offset") +	TailErr      = ErrorString("sqlite3: multiple statements") +	IsolationErr = ErrorString("sqlite3: unsupported isolation level") +	ValueErr     = ErrorString("sqlite3: unsupported value") +	NoVFSErr     = ErrorString("sqlite3: no such vfs: ") +) + +func AssertErr() ErrorString { +	msg := "sqlite3: assertion failed" +	if _, file, line, ok := runtime.Caller(1); ok { +		msg += " (" + file + ":" + strconv.Itoa(line) + ")" +	} +	return ErrorString(msg) +} + +func ErrorCodeString(rc uint32) string { +	switch rc { +	case ABORT_ROLLBACK: +		return "sqlite3: abort due to ROLLBACK" +	case ROW: +		return "sqlite3: another row available" +	case DONE: +		return "sqlite3: no more rows available" +	} +	switch rc & 0xff { +	case OK: +		return "sqlite3: not an error" +	case ERROR: +		return "sqlite3: SQL logic error" +	case INTERNAL: +		break +	case PERM: +		return "sqlite3: access permission denied" +	case ABORT: +		return "sqlite3: query aborted" +	case BUSY: +		return "sqlite3: database is locked" +	case LOCKED: +		return "sqlite3: database table is locked" +	case NOMEM: +		return "sqlite3: out of memory" +	case READONLY: +		return "sqlite3: attempt to write a readonly database" +	case INTERRUPT: +		return "sqlite3: interrupted" +	case IOERR: +		return "sqlite3: disk I/O error" +	case CORRUPT: +		return "sqlite3: database disk image is malformed" +	case NOTFOUND: +		return "sqlite3: unknown operation" +	case FULL: +		return "sqlite3: database or disk is full" +	case CANTOPEN: +		return "sqlite3: unable to open database file" +	case PROTOCOL: +		return "sqlite3: locking protocol" +	case FORMAT: +		break +	case SCHEMA: +		return "sqlite3: database schema has changed" +	case TOOBIG: +		return "sqlite3: string or blob too big" +	case CONSTRAINT: +		return "sqlite3: constraint failed" +	case MISMATCH: +		return "sqlite3: datatype mismatch" +	case MISUSE: +		return "sqlite3: bad parameter or other API misuse" +	case NOLFS: +		break +	case AUTH: +		return "sqlite3: authorization denied" +	case EMPTY: +		break +	case RANGE: +		return "sqlite3: column index out of range" +	case NOTADB: +		return "sqlite3: file is not a database" +	case NOTICE: +		return "sqlite3: notification message" +	case WARNING: +		return "sqlite3: warning message" +	} +	return "sqlite3: unknown error" +} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/func.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/func.go new file mode 100644 index 000000000..be7a47c2f --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/func.go @@ -0,0 +1,193 @@ +package util + +import ( +	"context" + +	"github.com/tetratelabs/wazero" +	"github.com/tetratelabs/wazero/api" +) + +type i32 interface{ ~int32 | ~uint32 } +type i64 interface{ ~int64 | ~uint64 } + +type funcVI[T0 i32] func(context.Context, api.Module, T0) + +func (fn funcVI[T0]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	fn(ctx, mod, T0(stack[0])) +} + +func ExportFuncVI[T0 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0)) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcVI[T0](fn), +			[]api.ValueType{api.ValueTypeI32}, nil). +		Export(name) +} + +type funcVII[T0, T1 i32] func(context.Context, api.Module, T0, T1) + +func (fn funcVII[T0, T1]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	fn(ctx, mod, T0(stack[0]), T1(stack[1])) +} + +func ExportFuncVII[T0, T1 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1)) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcVII[T0, T1](fn), +			[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, nil). +		Export(name) +} + +type funcVIII[T0, T1, T2 i32] func(context.Context, api.Module, T0, T1, T2) + +func (fn funcVIII[T0, T1, T2]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2])) +} + +func ExportFuncVIII[T0, T1, T2 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2)) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcVIII[T0, T1, T2](fn), +			[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, nil). +		Export(name) +} + +type funcVIIII[T0, T1, T2, T3 i32] func(context.Context, api.Module, T0, T1, T2, T3) + +func (fn funcVIIII[T0, T1, T2, T3]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3])) +} + +func ExportFuncVIIII[T0, T1, T2, T3 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3)) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcVIIII[T0, T1, T2, T3](fn), +			[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, nil). +		Export(name) +} + +type funcVIIIII[T0, T1, T2, T3, T4 i32] func(context.Context, api.Module, T0, T1, T2, T3, T4) + +func (fn funcVIIIII[T0, T1, T2, T3, T4]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3]), T4(stack[4])) +} + +func ExportFuncVIIIII[T0, T1, T2, T3, T4 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3, T4)) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcVIIIII[T0, T1, T2, T3, T4](fn), +			[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, nil). +		Export(name) +} + +type funcVIIIIJ[T0, T1, T2, T3 i32, T4 i64] func(context.Context, api.Module, T0, T1, T2, T3, T4) + +func (fn funcVIIIIJ[T0, T1, T2, T3, T4]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3]), T4(stack[4])) +} + +func ExportFuncVIIIIJ[T0, T1, T2, T3 i32, T4 i64](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3, T4)) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcVIIIIJ[T0, T1, T2, T3, T4](fn), +			[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI64}, nil). +		Export(name) +} + +type funcII[TR, T0 i32] func(context.Context, api.Module, T0) TR + +func (fn funcII[TR, T0]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	stack[0] = uint64(fn(ctx, mod, T0(stack[0]))) +} + +func ExportFuncII[TR, T0 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0) TR) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcII[TR, T0](fn), +			[]api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). +		Export(name) +} + +type funcIII[TR, T0, T1 i32] func(context.Context, api.Module, T0, T1) TR + +func (fn funcIII[TR, T0, T1]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]))) +} + +func ExportFuncIII[TR, T0, T1 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1) TR) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcIII[TR, T0, T1](fn), +			[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). +		Export(name) +} + +type funcIIII[TR, T0, T1, T2 i32] func(context.Context, api.Module, T0, T1, T2) TR + +func (fn funcIIII[TR, T0, T1, T2]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]))) +} + +func ExportFuncIIII[TR, T0, T1, T2 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2) TR) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcIIII[TR, T0, T1, T2](fn), +			[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). +		Export(name) +} + +type funcIIIII[TR, T0, T1, T2, T3 i32] func(context.Context, api.Module, T0, T1, T2, T3) TR + +func (fn funcIIIII[TR, T0, T1, T2, T3]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3]))) +} + +func ExportFuncIIIII[TR, T0, T1, T2, T3 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3) TR) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcIIIII[TR, T0, T1, T2, T3](fn), +			[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). +		Export(name) +} + +type funcIIIIII[TR, T0, T1, T2, T3, T4 i32] func(context.Context, api.Module, T0, T1, T2, T3, T4) TR + +func (fn funcIIIIII[TR, T0, T1, T2, T3, T4]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3]), T4(stack[4]))) +} + +func ExportFuncIIIIII[TR, T0, T1, T2, T3, T4 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3, T4) TR) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcIIIIII[TR, T0, T1, T2, T3, T4](fn), +			[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). +		Export(name) +} + +type funcIIIIIII[TR, T0, T1, T2, T3, T4, T5 i32] func(context.Context, api.Module, T0, T1, T2, T3, T4, T5) TR + +func (fn funcIIIIIII[TR, T0, T1, T2, T3, T4, T5]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3]), T4(stack[4]), T5(stack[5]))) +} + +func ExportFuncIIIIIII[TR, T0, T1, T2, T3, T4, T5 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3, T4, T5) TR) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcIIIIIII[TR, T0, T1, T2, T3, T4, T5](fn), +			[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). +		Export(name) +} + +type funcIIIIJ[TR, T0, T1, T2 i32, T3 i64] func(context.Context, api.Module, T0, T1, T2, T3) TR + +func (fn funcIIIIJ[TR, T0, T1, T2, T3]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3]))) +} + +func ExportFuncIIIIJ[TR, T0, T1, T2 i32, T3 i64](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3) TR) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcIIIIJ[TR, T0, T1, T2, T3](fn), +			[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI64}, []api.ValueType{api.ValueTypeI32}). +		Export(name) +} + +type funcIIJ[TR, T0 i32, T1 i64] func(context.Context, api.Module, T0, T1) TR + +func (fn funcIIJ[TR, T0, T1]) Call(ctx context.Context, mod api.Module, stack []uint64) { +	stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]))) +} + +func ExportFuncIIJ[TR, T0 i32, T1 i64](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1) TR) { +	mod.NewFunctionBuilder(). +		WithGoModuleFunction(funcIIJ[TR, T0, T1](fn), +			[]api.ValueType{api.ValueTypeI32, api.ValueTypeI64}, []api.ValueType{api.ValueTypeI32}). +		Export(name) +} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/handle.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/handle.go new file mode 100644 index 000000000..4584324c1 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/handle.go @@ -0,0 +1,65 @@ +package util + +import ( +	"context" +	"io" +) + +type handleState struct { +	handles []any +	holes   int +} + +func (s *handleState) CloseNotify(ctx context.Context, exitCode uint32) { +	for _, h := range s.handles { +		if c, ok := h.(io.Closer); ok { +			c.Close() +		} +	} +	s.handles = nil +	s.holes = 0 +} + +func GetHandle(ctx context.Context, id uint32) any { +	if id == 0 { +		return nil +	} +	s := ctx.Value(moduleKey{}).(*moduleState) +	return s.handles[^id] +} + +func DelHandle(ctx context.Context, id uint32) error { +	if id == 0 { +		return nil +	} +	s := ctx.Value(moduleKey{}).(*moduleState) +	a := s.handles[^id] +	s.handles[^id] = nil +	s.holes++ +	if c, ok := a.(io.Closer); ok { +		return c.Close() +	} +	return nil +} + +func AddHandle(ctx context.Context, a any) (id uint32) { +	if a == nil { +		panic(NilErr) +	} +	s := ctx.Value(moduleKey{}).(*moduleState) + +	// Find an empty slot. +	if s.holes > cap(s.handles)-len(s.handles) { +		for id, h := range s.handles { +			if h == nil { +				s.holes-- +				s.handles[id] = a +				return ^uint32(id) +			} +		} +	} + +	// Add a new slot. +	s.handles = append(s.handles, a) +	return -uint32(len(s.handles)) +} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/json.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/json.go new file mode 100644 index 000000000..c0ba38cf0 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/json.go @@ -0,0 +1,35 @@ +package util + +import ( +	"encoding/json" +	"strconv" +	"time" +	"unsafe" +) + +type JSON struct{ Value any } + +func (j JSON) Scan(value any) error { +	var buf []byte + +	switch v := value.(type) { +	case []byte: +		buf = v +	case string: +		buf = unsafe.Slice(unsafe.StringData(v), len(v)) +	case int64: +		buf = strconv.AppendInt(nil, v, 10) +	case float64: +		buf = strconv.AppendFloat(nil, v, 'g', -1, 64) +	case time.Time: +		buf = append(buf, '"') +		buf = v.AppendFormat(buf, time.RFC3339Nano) +		buf = append(buf, '"') +	case nil: +		buf = append(buf, "null"...) +	default: +		panic(AssertErr()) +	} + +	return json.Unmarshal(buf, j.Value) +} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/mem.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/mem.go new file mode 100644 index 000000000..a09523fd1 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/mem.go @@ -0,0 +1,134 @@ +package util + +import ( +	"bytes" +	"math" + +	"github.com/tetratelabs/wazero/api" +) + +func View(mod api.Module, ptr uint32, size uint64) []byte { +	if ptr == 0 { +		panic(NilErr) +	} +	if size > math.MaxUint32 { +		panic(RangeErr) +	} +	if size == 0 { +		return nil +	} +	buf, ok := mod.Memory().Read(ptr, uint32(size)) +	if !ok { +		panic(RangeErr) +	} +	return buf +} + +func ReadUint8(mod api.Module, ptr uint32) uint8 { +	if ptr == 0 { +		panic(NilErr) +	} +	v, ok := mod.Memory().ReadByte(ptr) +	if !ok { +		panic(RangeErr) +	} +	return v +} + +func ReadUint32(mod api.Module, ptr uint32) uint32 { +	if ptr == 0 { +		panic(NilErr) +	} +	v, ok := mod.Memory().ReadUint32Le(ptr) +	if !ok { +		panic(RangeErr) +	} +	return v +} + +func WriteUint8(mod api.Module, ptr uint32, v uint8) { +	if ptr == 0 { +		panic(NilErr) +	} +	ok := mod.Memory().WriteByte(ptr, v) +	if !ok { +		panic(RangeErr) +	} +} + +func WriteUint32(mod api.Module, ptr uint32, v uint32) { +	if ptr == 0 { +		panic(NilErr) +	} +	ok := mod.Memory().WriteUint32Le(ptr, v) +	if !ok { +		panic(RangeErr) +	} +} + +func ReadUint64(mod api.Module, ptr uint32) uint64 { +	if ptr == 0 { +		panic(NilErr) +	} +	v, ok := mod.Memory().ReadUint64Le(ptr) +	if !ok { +		panic(RangeErr) +	} +	return v +} + +func WriteUint64(mod api.Module, ptr uint32, v uint64) { +	if ptr == 0 { +		panic(NilErr) +	} +	ok := mod.Memory().WriteUint64Le(ptr, v) +	if !ok { +		panic(RangeErr) +	} +} + +func ReadFloat64(mod api.Module, ptr uint32) float64 { +	return math.Float64frombits(ReadUint64(mod, ptr)) +} + +func WriteFloat64(mod api.Module, ptr uint32, v float64) { +	WriteUint64(mod, ptr, math.Float64bits(v)) +} + +func ReadString(mod api.Module, ptr, maxlen uint32) string { +	if ptr == 0 { +		panic(NilErr) +	} +	switch maxlen { +	case 0: +		return "" +	case math.MaxUint32: +		// avoid overflow +	default: +		maxlen = maxlen + 1 +	} +	mem := mod.Memory() +	buf, ok := mem.Read(ptr, maxlen) +	if !ok { +		buf, ok = mem.Read(ptr, mem.Size()-ptr) +		if !ok { +			panic(RangeErr) +		} +	} +	if i := bytes.IndexByte(buf, 0); i < 0 { +		panic(NoNulErr) +	} else { +		return string(buf[:i]) +	} +} + +func WriteBytes(mod api.Module, ptr uint32, b []byte) { +	buf := View(mod, ptr, uint64(len(b))) +	copy(buf, b) +} + +func WriteString(mod api.Module, ptr uint32, s string) { +	buf := View(mod, ptr, uint64(len(s)+1)) +	buf[len(s)] = 0 +	copy(buf, s) +} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap.go new file mode 100644 index 000000000..6783c9612 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap.go @@ -0,0 +1,97 @@ +//go:build (darwin || linux) && (amd64 || arm64 || riscv64) && !(sqlite3_noshm || sqlite3_nosys) + +package util + +import ( +	"context" +	"os" +	"unsafe" + +	"github.com/tetratelabs/wazero/api" +	"github.com/tetratelabs/wazero/experimental" +	"golang.org/x/sys/unix" +) + +func withAllocator(ctx context.Context) context.Context { +	return experimental.WithMemoryAllocator(ctx, +		experimental.MemoryAllocatorFunc(virtualAlloc)) +} + +type mmapState struct { +	regions []*MappedRegion +} + +func (s *mmapState) new(ctx context.Context, mod api.Module, size int32) *MappedRegion { +	// Find unused region. +	for _, r := range s.regions { +		if !r.used && r.size == size { +			return r +		} +	} + +	// Allocate page aligned memmory. +	alloc := mod.ExportedFunction("aligned_alloc") +	stack := [2]uint64{ +		uint64(unix.Getpagesize()), +		uint64(size), +	} +	if err := alloc.CallWithStack(ctx, stack[:]); err != nil { +		panic(err) +	} +	if stack[0] == 0 { +		panic(OOMErr) +	} + +	// Save the newly allocated region. +	ptr := uint32(stack[0]) +	buf := View(mod, ptr, uint64(size)) +	addr := uintptr(unsafe.Pointer(&buf[0])) +	s.regions = append(s.regions, &MappedRegion{ +		Ptr:  ptr, +		addr: addr, +		size: size, +	}) +	return s.regions[len(s.regions)-1] +} + +type MappedRegion struct { +	addr uintptr +	Ptr  uint32 +	size int32 +	used bool +} + +func MapRegion(ctx context.Context, mod api.Module, f *os.File, offset int64, size int32, prot int) (*MappedRegion, error) { +	s := ctx.Value(moduleKey{}).(*moduleState) +	r := s.new(ctx, mod, size) +	err := r.mmap(f, offset, prot) +	if err != nil { +		return nil, err +	} +	return r, nil +} + +func (r *MappedRegion) Unmap() error { +	// We can't munmap the region, otherwise it could be remaped. +	// Instead, convert it to a protected, private, anonymous mapping. +	// If successful, it can be reused for a subsequent mmap. +	_, err := mmap(r.addr, uintptr(r.size), +		unix.PROT_NONE, unix.MAP_PRIVATE|unix.MAP_ANON|unix.MAP_FIXED, +		-1, 0) +	r.used = err != nil +	return err +} + +func (r *MappedRegion) mmap(f *os.File, offset int64, prot int) error { +	_, err := mmap(r.addr, uintptr(r.size), +		prot, unix.MAP_SHARED|unix.MAP_FIXED, +		int(f.Fd()), offset) +	r.used = err == nil +	return err +} + +// We need the low level mmap for MAP_FIXED to work. +// Bind the syscall version hoping that it is more stable. + +//go:linkname mmap syscall.mmap +func mmap(addr, length uintptr, prot, flag, fd int, pos int64) (*byte, error) diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap_other.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap_other.go new file mode 100644 index 000000000..1e81c9fd3 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap_other.go @@ -0,0 +1,21 @@ +//go:build !(darwin || linux) || !(amd64 || arm64 || riscv64) || sqlite3_noshm || sqlite3_nosys + +package util + +import ( +	"context" + +	"github.com/tetratelabs/wazero/experimental" +) + +type mmapState struct{} + +func withAllocator(ctx context.Context) context.Context { +	return experimental.WithMemoryAllocator(ctx, +		experimental.MemoryAllocatorFunc(func(cap, max uint64) experimental.LinearMemory { +			if cap == max { +				return virtualAlloc(cap, max) +			} +			return sliceAlloc(cap, max) +		})) +} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/module.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/module.go new file mode 100644 index 000000000..22793e972 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/module.go @@ -0,0 +1,21 @@ +package util + +import ( +	"context" + +	"github.com/tetratelabs/wazero/experimental" +) + +type moduleKey struct{} +type moduleState struct { +	mmapState +	handleState +} + +func NewContext(ctx context.Context) context.Context { +	state := new(moduleState) +	ctx = withAllocator(ctx) +	ctx = experimental.WithCloseNotifier(ctx, state) +	ctx = context.WithValue(ctx, moduleKey{}, state) +	return ctx +} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/pointer.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/pointer.go new file mode 100644 index 000000000..eae4dae17 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/pointer.go @@ -0,0 +1,11 @@ +package util + +type Pointer[T any] struct{ Value T } + +func (p Pointer[T]) unwrap() any { return p.Value } + +type PointerUnwrap interface{ unwrap() any } + +func UnwrapPointer(p PointerUnwrap) any { +	return p.unwrap() +} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/reflect.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/reflect.go new file mode 100644 index 000000000..3104a7cf3 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/reflect.go @@ -0,0 +1,10 @@ +package util + +import "reflect" + +func ReflectType(v reflect.Value) reflect.Type { +	if v.Kind() != reflect.Invalid { +		return v.Type() +	} +	return nil +} | 
