Update pkg to same Node addon Header #8
13
array.go
13
array.go
@ -70,3 +70,16 @@ func (arr *Array) Seq() iter.Seq[ValueType] {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (arr *Array) Append(values ...ValueType) error {
|
||||
length, err := arr.Length()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for valueIndex := range values {
|
||||
if err = arr.Set(length+valueIndex, values[valueIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
20
boolean.go
Normal file
20
boolean.go
Normal file
@ -0,0 +1,20 @@
|
||||
package napi
|
||||
|
||||
import "sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi"
|
||||
|
||||
type Boolean struct{ value }
|
||||
|
||||
// Convert [ValueType] to [*Boolean]
|
||||
func ToBoolean(o ValueType) *Boolean { return &Boolean{o} }
|
||||
|
||||
func CreateBoolean(env EnvType, value bool) (*Boolean, error) {
|
||||
v, err := mustValueErr(napi.GetBoolean(env.NapiValue(), value))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ToBoolean(N_APIValue(env, v)), nil
|
||||
}
|
||||
|
||||
func (bo *Boolean) Value() (bool, error) {
|
||||
return mustValueErr(napi.GetValueBool(bo.NapiEnv(), bo.NapiValue()))
|
||||
}
|
36
buffer.go
Normal file
36
buffer.go
Normal file
@ -0,0 +1,36 @@
|
||||
package napi
|
||||
|
||||
import "sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi"
|
||||
|
||||
type Buffer struct{ value }
|
||||
|
||||
// Convert [ValueType] to [*Buffer].
|
||||
func ToBuffer(o ValueType) *Buffer { return &Buffer{o} }
|
||||
|
||||
// Create new Buffer with length
|
||||
func CreateBuffer(env EnvType, length int) (*Buffer, error) {
|
||||
napiValue, err := mustValueErr(napi.CreateBuffer(env.NapiValue(), length))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ToBuffer(N_APIValue(env, napiValue)), nil
|
||||
}
|
||||
|
||||
// Copy []byte to Node::Buffer struct
|
||||
func CopyBuffer(env EnvType, buff []byte) (*Buffer, error) {
|
||||
napiValue, err := mustValueErr(napi.CreateBufferCopy(env.NapiValue(), buff))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ToBuffer(N_APIValue(env, napiValue)), nil
|
||||
}
|
||||
|
||||
// Get size of buffer
|
||||
func (buff *Buffer) Length() (int, error) {
|
||||
return mustValueErr(napi.GetBufferInfoSize(buff.NapiEnv(), buff.NapiValue()))
|
||||
}
|
||||
|
||||
// return []byte from Buffer value
|
||||
func (buff *Buffer) Data() ([]byte, error) {
|
||||
return mustValueErr(napi.GetBufferInfoData(buff.NapiEnv(), buff.NapiValue()))
|
||||
}
|
29
date.go
Normal file
29
date.go
Normal file
@ -0,0 +1,29 @@
|
||||
package napi
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi"
|
||||
)
|
||||
|
||||
type Date struct{ value }
|
||||
|
||||
// Convert [ValueType] to [*Date]
|
||||
func ToDate(o ValueType) *Date { return &Date{o} }
|
||||
|
||||
func CreateDate(env EnvType, date time.Time) (*Date, error) {
|
||||
value, err := mustValueErr(napi.CreateDate(env.NapiValue(), float64(date.UnixMilli())))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Date{value: &Value{env: env, valueOf: value}}, nil
|
||||
}
|
||||
|
||||
// Get time from [*Date] object.
|
||||
func (d Date) Time() (time.Time, error) {
|
||||
timeFloat, err := mustValueErr(napi.GetDateValue(d.NapiEnv(), d.NapiValue()))
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
return time.UnixMilli(int64(timeFloat)), nil
|
||||
}
|
@ -24,6 +24,8 @@ package entry
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
gonapi "sirherobrine23.com.br/Sirherobrine23/napi-go"
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi"
|
||||
)
|
||||
@ -37,6 +39,17 @@ func initializeModule(cEnv C.napi_env, cExports C.napi_value) C.napi_value {
|
||||
env, exports := napi.Env(cEnv), napi.Value(cExports)
|
||||
napi.InitializeInstanceData(env)
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
switch v := err.(type) {
|
||||
case error:
|
||||
gonapi.ThrowError(gonapi.N_APIEnv(env), "", v.Error())
|
||||
default:
|
||||
gonapi.ThrowError(gonapi.N_APIEnv(env), "", fmt.Sprintf("%s", v))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for _, registerCall := range modFuncInit {
|
||||
registerCall(env, exports)
|
||||
}
|
||||
@ -44,7 +57,7 @@ func initializeModule(cEnv C.napi_env, cExports C.napi_value) C.napi_value {
|
||||
return cExports
|
||||
}
|
||||
|
||||
func Register(fn func(gonapi.EnvType, *gonapi.Object)) {
|
||||
func Register(fn func(env gonapi.EnvType, export *gonapi.Object)) {
|
||||
modFuncInit = append(modFuncInit, func(env napi.Env, object napi.Value) {
|
||||
registerEnv := gonapi.N_APIEnv(env)
|
||||
registerObj := gonapi.ToObject(gonapi.N_APIValue(registerEnv, object))
|
||||
|
37
error.go
Normal file
37
error.go
Normal file
@ -0,0 +1,37 @@
|
||||
package napi
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi"
|
||||
)
|
||||
|
||||
type Error struct{ value }
|
||||
|
||||
func ToError(o ValueType) *Error { return &Error{o} }
|
||||
|
||||
func CreateError(env EnvType, msg string) (*Error, error) {
|
||||
napiMsg, err := CreateString(env, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
napiValue, err := mustValueErr(napi.CreateError(env.NapiValue(), nil, napiMsg.NapiValue()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ToError(N_APIValue(env, napiValue)), nil
|
||||
}
|
||||
|
||||
func (er *Error) ThrowAsJavaScriptException() error {
|
||||
return singleMustValueErr(napi.Throw(er.NapiEnv(), er.NapiValue()))
|
||||
}
|
||||
|
||||
// This throws a JavaScript Error with the text provided.
|
||||
func ThrowError(env EnvType, code, err string) error {
|
||||
if code == "" {
|
||||
stackTraceBuf := make([]byte, 8192)
|
||||
stackTraceSz := runtime.Stack(stackTraceBuf, false)
|
||||
code = string(stackTraceBuf[:stackTraceSz])
|
||||
}
|
||||
return singleMustValueErr(napi.ThrowError(env.NapiValue(), code, err))
|
||||
}
|
80
example/test.go
Normal file
80
example/test.go
Normal file
@ -0,0 +1,80 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/netip"
|
||||
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go"
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go/entry"
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go/js"
|
||||
)
|
||||
|
||||
type Test struct {
|
||||
Int int
|
||||
String string
|
||||
Sub []any
|
||||
}
|
||||
|
||||
func init() {
|
||||
entry.Register(func(env napi.EnvType, export *napi.Object) {
|
||||
inNode, _ := napi.CreateString(env, "from golang napi string")
|
||||
inNode2, _ := napi.CopyBuffer(env, []byte{1, 0, 244, 21})
|
||||
toGoReflect := &Test{
|
||||
Int: 14,
|
||||
String: "From golang",
|
||||
Sub: []any{
|
||||
1,
|
||||
[]string{"test", "gopher"},
|
||||
[]bool{false, true},
|
||||
[]int{23, 244, 10, 2024, 2025, 2000},
|
||||
map[string]string{"exampleMap": "test"},
|
||||
map[int]string{1: "one"},
|
||||
map[bool]string{false: "false", true: "true"},
|
||||
map[[2]string]string{[2]string{"go"}: "example"},
|
||||
netip.IPv4Unspecified(),
|
||||
netip.IPv6Unspecified(),
|
||||
netip.AddrPortFrom(netip.IPv6Unspecified(), 19132),
|
||||
nil,
|
||||
true,
|
||||
false,
|
||||
inNode,
|
||||
inNode2,
|
||||
func() {
|
||||
println("called in go")
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
napiStruct, err := js.ValueOf(env, toGoReflect)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
export.Set("goStruct", napiStruct)
|
||||
|
||||
fnCall, err := js.GoFuncOf(env, func(call ...any) (string, error) {
|
||||
d, err := json.MarshalIndent(call, "", " ")
|
||||
if err == nil {
|
||||
println(string(d))
|
||||
}
|
||||
return string(d), err
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
export.Set("printAny", fnCall)
|
||||
|
||||
fnCallStruct, err := js.GoFuncOf(env, func(call ...Test) (string, error) {
|
||||
d, err := json.MarshalIndent(call, "", " ")
|
||||
if err == nil {
|
||||
println(string(d))
|
||||
}
|
||||
return string(d), err
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
export.Set("printTestStruct", fnCallStruct)
|
||||
})
|
||||
}
|
||||
|
||||
func main() {}
|
96
function.go
Normal file
96
function.go
Normal file
@ -0,0 +1,96 @@
|
||||
package napi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi"
|
||||
)
|
||||
|
||||
type Function struct{ value }
|
||||
|
||||
// Function to call on Javascript caller
|
||||
type Callback func(env EnvType, this ValueType, args []ValueType) (ValueType, error)
|
||||
|
||||
// Convert [ValueType] to [*Function]
|
||||
func ToFunction(o ValueType) *Function { return &Function{o} }
|
||||
|
||||
func CreateFunction(env EnvType, name string, callback Callback) (*Function, error) {
|
||||
return CreateFunctionNapi(env, name, func(napiEnv napi.Env, info napi.CallbackInfo) napi.Value {
|
||||
env := N_APIEnv(napiEnv)
|
||||
cbInfo, err := mustValueErr(napi.GetCbInfo(napiEnv, info))
|
||||
if err != nil {
|
||||
ThrowError(env, "", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
this := N_APIValue(env, cbInfo.This)
|
||||
args := make([]ValueType, len(cbInfo.Args))
|
||||
for i, cbArg := range cbInfo.Args {
|
||||
args[i] = N_APIValue(env, cbArg)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
switch v := err.(type) {
|
||||
case error:
|
||||
ThrowError(env, "", v.Error())
|
||||
default:
|
||||
ThrowError(env, "", fmt.Sprintf("panic recover: %s", err))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
res, err := callback(env, this, args)
|
||||
switch {
|
||||
case err != nil:
|
||||
ThrowError(env, "", err.Error())
|
||||
return nil
|
||||
case res == nil:
|
||||
und, _ := env.Undefined()
|
||||
return und.NapiValue()
|
||||
default:
|
||||
typeOf, _ := res.Type()
|
||||
if typeOf == TypeError {
|
||||
ToError(res).ThrowAsJavaScriptException()
|
||||
return nil
|
||||
}
|
||||
return res.NapiValue()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func CreateFunctionNapi(env EnvType, name string, callback napi.Callback) (*Function, error) {
|
||||
fnCall, err := mustValueErr(napi.CreateFunction(env.NapiValue(), name, callback))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ToFunction(N_APIValue(env, fnCall)), nil
|
||||
}
|
||||
|
||||
func (fn *Function) internalCall(this napi.Value, argc int, argv []napi.Value) (ValueType, error) {
|
||||
// napi_call_function(env, global, add_two, argc, argv, &return_val);
|
||||
res, err := mustValueErr(napi.CallFunction(fn.NapiEnv(), this, fn.NapiValue(), argc, argv))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return N_APIValue(fn.Env(), res), nil
|
||||
}
|
||||
|
||||
// Call function with custom global/this value
|
||||
func (fn *Function) CallWithGlobal(this ValueType, args ...ValueType) (ValueType, error) {
|
||||
argc := len(args)
|
||||
argv := make([]napi.Value, argc)
|
||||
for index := range argc {
|
||||
argv[index] = args[index].NapiValue()
|
||||
}
|
||||
return fn.internalCall(this.NapiValue(), argc, argv)
|
||||
}
|
||||
|
||||
// Call function with args
|
||||
func (fn *Function) Call(args ...ValueType) (ValueType, error) {
|
||||
global, err := fn.Env().Global()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fn.CallWithGlobal(global, args...)
|
||||
}
|
@ -201,6 +201,28 @@ func GetValueStringUtf8(env Env, value Value) (string, Status) {
|
||||
), status
|
||||
}
|
||||
|
||||
func GetValueStringUtf16(env Env, value Value) ([]uint16, Status) {
|
||||
bufsize := C.size_t(0)
|
||||
var strsize C.size_t
|
||||
|
||||
status := Status(C.napi_get_value_string_utf16(C.napi_env(env), C.napi_value(value), nil, bufsize, &strsize))
|
||||
if status != StatusOK {
|
||||
return nil, status
|
||||
}
|
||||
|
||||
strsize++
|
||||
cstr := (*C.char16_t)(C.malloc(C.sizeof_char * strsize))
|
||||
defer C.free(unsafe.Pointer(cstr))
|
||||
|
||||
status = Status(C.napi_get_value_string_utf16(C.napi_env(env), C.napi_value(value), cstr, strsize, &strsize))
|
||||
if status != StatusOK {
|
||||
return nil, status
|
||||
}
|
||||
runes := make([]uint16, strsize)
|
||||
copy(runes, (*[1 << 30]uint16)(unsafe.Pointer(cstr))[:strsize:strsize])
|
||||
return runes, status
|
||||
}
|
||||
|
||||
func SetProperty(env Env, object, key, value Value) Status {
|
||||
return Status(C.napi_set_property(
|
||||
C.napi_env(env),
|
||||
@ -340,20 +362,6 @@ func GetInstanceData(env Env) (any, Status) {
|
||||
return provider.GetUserData(), status
|
||||
}
|
||||
|
||||
func CreateBuffer(env Env, length int) (Value, []byte, Status) {
|
||||
var result Value
|
||||
data := make([]byte, length)
|
||||
dataPtr := unsafe.Pointer(&data[0])
|
||||
|
||||
status := Status(C.napi_create_buffer(
|
||||
C.napi_env(env),
|
||||
C.size_t(length),
|
||||
&dataPtr,
|
||||
(*C.napi_value)(unsafe.Pointer(&result)),
|
||||
))
|
||||
return result, data, status
|
||||
}
|
||||
|
||||
func CreateExternal(env Env, data unsafe.Pointer, finalize Finalize, finalizeHint unsafe.Pointer) (Value, Status) {
|
||||
var result Value
|
||||
finalizer := FinalizeToFinalizer(finalize)
|
||||
@ -469,18 +477,27 @@ func CoerceToString(env Env, value Value) (Value, Status) {
|
||||
return result, status
|
||||
}
|
||||
|
||||
func CreateBufferCopy(env Env, data []byte) (Value, *byte, Status) {
|
||||
func CreateBuffer(env Env, length int) (Value, Status) {
|
||||
var result Value
|
||||
status := Status(C.napi_create_buffer(
|
||||
C.napi_env(env),
|
||||
C.size_t(length),
|
||||
nil,
|
||||
(*C.napi_value)(unsafe.Pointer(&result)),
|
||||
))
|
||||
return result, status
|
||||
}
|
||||
|
||||
func CreateBufferCopy(env Env, data []byte) (Value, Status) {
|
||||
var result Value
|
||||
var copiedData *byte
|
||||
copiedDataPtr := unsafe.Pointer(&copiedData)
|
||||
status := Status(C.napi_create_buffer_copy(
|
||||
C.napi_env(env),
|
||||
C.size_t(len(data)),
|
||||
unsafe.Pointer(&data[0]),
|
||||
&copiedDataPtr,
|
||||
nil,
|
||||
(*C.napi_value)(unsafe.Pointer(&result)),
|
||||
))
|
||||
return result, copiedData, status
|
||||
return result, status
|
||||
}
|
||||
|
||||
func GetBufferInfo(env Env, value Value) (*byte, int, Status) {
|
||||
@ -488,16 +505,29 @@ func GetBufferInfo(env Env, value Value) (*byte, int, Status) {
|
||||
var length C.size_t
|
||||
|
||||
dataPtr := unsafe.Pointer(&data)
|
||||
|
||||
status := Status(C.napi_get_buffer_info(
|
||||
C.napi_env(env),
|
||||
C.napi_value(value),
|
||||
&dataPtr,
|
||||
&length,
|
||||
))
|
||||
status := Status(C.napi_get_buffer_info(C.napi_env(env), C.napi_value(value), &dataPtr, &length))
|
||||
return data, int(length), status
|
||||
}
|
||||
|
||||
func GetBufferInfoSize(env Env, value Value) (int, Status) {
|
||||
var length C.size_t
|
||||
status := Status(C.napi_get_buffer_info(C.napi_env(env), C.napi_value(value), nil, &length))
|
||||
return int(length), status
|
||||
}
|
||||
|
||||
func GetBufferInfoData(env Env, value Value) (buff []byte, status Status) {
|
||||
var data *byte
|
||||
var length C.size_t
|
||||
|
||||
dataPtr := unsafe.Pointer(&data)
|
||||
status = Status(C.napi_get_buffer_info(C.napi_env(env), C.napi_value(value), &dataPtr, &length))
|
||||
if status == StatusOK {
|
||||
buff = make([]byte, length)
|
||||
copy(buff, (*[1 << 30]byte)(unsafe.Pointer(data))[:length:length])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetArrayLength(env Env, value Value) (int, Status) {
|
||||
var length C.uint32_t
|
||||
status := Status(C.napi_get_array_length(
|
||||
|
21
js/funcof.md
Normal file
21
js/funcof.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Go functions conversion to Javascript functions
|
||||
|
||||
## Simples conversions
|
||||
|
||||
| Go | Node |
|
||||
| --------------------------------- | ------------------------------------------- |
|
||||
| `func()` | `function(): void` |
|
||||
| `func() value` | `function(): value` |
|
||||
| `func(value1, value2)` | `function(value1, value2): void` |
|
||||
| `func() (value1, value2)` | `function(): [value1, value2]` |
|
||||
| `func(value1, value2, values...)` | `function(value1, value2, ...values): void` |
|
||||
| `func(values...)` | `function(...values): void` |
|
||||
|
||||
## Error throw
|
||||
|
||||
| Go | Node |
|
||||
| ------------------------------------------ | --------------------------------------------------- |
|
||||
| `func() error` | `function(): throw Error` |
|
||||
| `func(value1, value2) error` | `function(value1, value2): throw Error` |
|
||||
| `func() (value, error)` | `function(): value \|\| throw Error` |
|
||||
| `func(value1, value2) (...nValues, error)` | `function(value1, value2): (Array \|\|throw Error)` |
|
575
js/js.go
Normal file
575
js/js.go
Normal file
@ -0,0 +1,575 @@
|
||||
package js
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go"
|
||||
)
|
||||
|
||||
const propertiesTagName = "napi"
|
||||
|
||||
// Convert go types to valid NAPI, if not conpatible return Undefined.
|
||||
func ValueOf(env napi.EnvType, value any) (napiValue napi.ValueType, err error) {
|
||||
return valueOf(env, reflect.ValueOf(value))
|
||||
}
|
||||
|
||||
// Convert NAPI value to Go values
|
||||
func ValueFrom(napiValue napi.ValueType, v any) error {
|
||||
ptr := reflect.ValueOf(v)
|
||||
if ptr.Kind() != reflect.Pointer {
|
||||
return fmt.Errorf("require point to convert napi value to go value")
|
||||
}
|
||||
return valueFrom(napiValue, ptr.Elem())
|
||||
}
|
||||
|
||||
func valueOf(env napi.EnvType, ptr reflect.Value) (napiValue napi.ValueType, err error) {
|
||||
defer func(err *error) {
|
||||
if err2 := recover(); err2 != nil {
|
||||
switch v := err2.(type) {
|
||||
case error:
|
||||
*err = v
|
||||
default:
|
||||
*err = fmt.Errorf("panic recover: %s", err2)
|
||||
}
|
||||
}
|
||||
}(&err)
|
||||
|
||||
if !ptr.IsValid() || ptr.IsZero() {
|
||||
return env.Undefined()
|
||||
}
|
||||
|
||||
// Marshalers
|
||||
if ptr.CanInterface() {
|
||||
switch v := ptr.Interface().(type) {
|
||||
case napi.ValueType:
|
||||
return v, nil
|
||||
case time.Time:
|
||||
return napi.CreateDate(env, v)
|
||||
case encoding.TextMarshaler:
|
||||
data, err := v.MarshalText()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return napi.CreateString(env, string(data))
|
||||
case json.Marshaler:
|
||||
var pointData any
|
||||
data, err := v.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if err = json.Unmarshal(data, &pointData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ValueOf(env, pointData)
|
||||
}
|
||||
}
|
||||
|
||||
ptrType := ptr.Type()
|
||||
switch ptrType.Kind() {
|
||||
case reflect.Pointer:
|
||||
return valueOf(env, ptr.Elem())
|
||||
case reflect.String:
|
||||
return napi.CreateString(env, ptr.String())
|
||||
case reflect.Bool:
|
||||
return napi.CreateBoolean(env, ptr.Bool())
|
||||
case reflect.Int, reflect.Uint, reflect.Int32, reflect.Uint32, reflect.Float32, reflect.Int8, reflect.Uint8, reflect.Int16, reflect.Uint16:
|
||||
return napi.CreateNumber(env, ptr.Int())
|
||||
case reflect.Float64:
|
||||
return napi.CreateNumber(env, ptr.Float())
|
||||
case reflect.Int64, reflect.Uint64:
|
||||
return napi.CreateBigint(env, ptr.Int())
|
||||
case reflect.Func:
|
||||
return funcOf(env, ptr)
|
||||
case reflect.Slice, reflect.Array:
|
||||
arr, err := napi.CreateArray(env, ptr.Len())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for index := range ptr.Len() {
|
||||
value, err := valueOf(env, ptr.Index(index))
|
||||
if err != nil {
|
||||
return arr, err
|
||||
} else if err = arr.Set(index, value); err != nil {
|
||||
return arr, err
|
||||
}
|
||||
}
|
||||
return arr, nil
|
||||
case reflect.Struct:
|
||||
obj, err := napi.CreateObject(env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for keyIndex := range ptrType.NumField() {
|
||||
field, fieldType := ptr.Field(keyIndex), ptrType.Field(keyIndex)
|
||||
if !fieldType.IsExported() || fieldType.Tag.Get(propertiesTagName) == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
value, err := valueOf(env, field)
|
||||
if err != nil {
|
||||
return obj, err
|
||||
}
|
||||
|
||||
typeof, err := value.Type()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyNamed := fieldType.Name
|
||||
if strings.Count(fieldType.Tag.Get(propertiesTagName), ",") > 0 {
|
||||
fields := strings.SplitN(fieldType.Tag.Get(propertiesTagName), ",", 2)
|
||||
keyNamed = fields[0]
|
||||
switch fields[1] {
|
||||
case "omitempty":
|
||||
switch typeof {
|
||||
case napi.TypeUndefined, napi.TypeNull, napi.TypeUnkown:
|
||||
continue
|
||||
case napi.TypeString:
|
||||
str, err := napi.ToString(value).Utf8Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if str == "" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
case "omitzero":
|
||||
switch typeof {
|
||||
case napi.TypeUndefined, napi.TypeNull, napi.TypeUnkown:
|
||||
continue
|
||||
case napi.TypeDate:
|
||||
value, err := napi.ToDate(value).Time()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if value.Unix() == 0 {
|
||||
continue
|
||||
}
|
||||
case napi.TypeBigInt:
|
||||
value, err := napi.ToBigint(value).Int64()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if value == 0 {
|
||||
continue
|
||||
}
|
||||
case napi.TypeNumber:
|
||||
value, err := napi.ToNumber(value).Int()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if value == 0 {
|
||||
continue
|
||||
}
|
||||
case napi.TypeArray:
|
||||
value, err := napi.ToArray(value).Length()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if value == 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err = obj.Set(keyNamed, value); err != nil {
|
||||
return obj, err
|
||||
}
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
case reflect.Map:
|
||||
obj, err := napi.CreateObject(env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for ptrKey, ptrValue := range ptr.Seq2() {
|
||||
key, err := valueOf(env, ptrKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
value, err := valueOf(env, ptrValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if err = obj.SetWithValue(key, value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return obj, nil
|
||||
case reflect.Interface:
|
||||
if ptr.IsValid() {
|
||||
if ptr.IsNil() {
|
||||
return env.Null()
|
||||
} else if ptr.CanInterface() {
|
||||
return valueOf(env, reflect.ValueOf(ptr.Interface()))
|
||||
}
|
||||
}
|
||||
}
|
||||
return env.Undefined()
|
||||
}
|
||||
|
||||
func valueFrom(napiValue napi.ValueType, ptr reflect.Value) error {
|
||||
typeOf, err := napiValue.Type()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ptrType := ptr.Type()
|
||||
switch ptrType.Kind() {
|
||||
case reflect.Pointer:
|
||||
return valueFrom(napiValue, ptr.Elem())
|
||||
case reflect.Interface:
|
||||
// Check if is any and can set
|
||||
if ptr.CanSet() && ptrType == reflect.TypeFor[any]() {
|
||||
switch typeOf {
|
||||
case napi.TypeNull, napi.TypeUndefined, napi.TypeUnkown:
|
||||
ptr.Set(reflect.Zero(ptrType))
|
||||
return nil
|
||||
case napi.TypeBoolean:
|
||||
valueOf, err := napi.ToBoolean(napiValue).Value()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.Set(reflect.ValueOf(valueOf))
|
||||
case napi.TypeNumber:
|
||||
numberValue, err := napi.ToNumber(napiValue).Float()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.Set(reflect.ValueOf(numberValue))
|
||||
case napi.TypeBigInt:
|
||||
numberValue, err := napi.ToBigint(napiValue).Int64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.Set(reflect.ValueOf(numberValue))
|
||||
case napi.TypeString:
|
||||
str, err := napi.ToString(napiValue).Utf8Value()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.Set(reflect.ValueOf(str))
|
||||
case napi.TypeDate:
|
||||
timeDate, err := napi.ToDate(napiValue).Time()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.Set(reflect.ValueOf(timeDate))
|
||||
case napi.TypeArray:
|
||||
napiArray := napi.ToArray(napiValue)
|
||||
size, err := napiArray.Length()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
value := reflect.MakeSlice(reflect.SliceOf(ptrType), size, size)
|
||||
for index := range size {
|
||||
napiValue, err := napiArray.Get(index)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if err = valueFrom(napiValue, value.Index(index)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ptr.Set(value)
|
||||
case napi.TypeBuffer:
|
||||
buff, err := napi.ToBuffer(napiValue).Data()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.Set(reflect.ValueOf(buff))
|
||||
case napi.TypeObject:
|
||||
obj := napi.ToObject(napiValue)
|
||||
goMap := reflect.MakeMap(reflect.MapOf(reflect.TypeFor[string](), reflect.TypeFor[any]()))
|
||||
for keyName, value := range obj.Seq() {
|
||||
valueOf := reflect.New(reflect.TypeFor[any]())
|
||||
if err := valueFrom(value, valueOf); err != nil {
|
||||
return err
|
||||
}
|
||||
goMap.SetMapIndex(reflect.ValueOf(keyName), valueOf)
|
||||
}
|
||||
ptr.Set(goMap)
|
||||
case napi.TypeFunction:
|
||||
ptr.Set(reflect.ValueOf(napi.ToFunction(napiValue)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("cannot set value, returned %s", typeOf)
|
||||
}
|
||||
|
||||
switch typeOf {
|
||||
case napi.TypeNull, napi.TypeUndefined, napi.TypeUnkown:
|
||||
switch ptrType.Kind() {
|
||||
case reflect.Interface, reflect.Pointer:
|
||||
ptr.Set(reflect.Zero(ptrType))
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("cannot set value, returned %s", typeOf)
|
||||
}
|
||||
case napi.TypeBoolean:
|
||||
switch ptr.Kind() {
|
||||
case reflect.Bool:
|
||||
valueOf, err := napi.ToBoolean(napiValue).Value()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.SetBool(valueOf)
|
||||
default:
|
||||
return fmt.Errorf("cannot set boolean value to %s", ptr.Kind())
|
||||
}
|
||||
case napi.TypeNumber:
|
||||
switch ptrType.Kind() {
|
||||
case reflect.Float32, reflect.Float64:
|
||||
floatValue, err := napi.ToNumber(napiValue).Float()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.SetFloat(floatValue)
|
||||
return nil
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
numberValue, err := napi.ToNumber(napiValue).Int()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.SetInt(numberValue)
|
||||
return nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
numberValue, err := napi.ToNumber(napiValue).Int()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.SetUint(uint64(numberValue))
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("cannot set number value to %s", ptr.Kind())
|
||||
}
|
||||
case napi.TypeBigInt:
|
||||
switch ptrType.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
numberValue, err := napi.ToNumber(napiValue).Int()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.SetInt(numberValue)
|
||||
return nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
numberValue, err := napi.ToNumber(napiValue).Int()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.SetUint(uint64(numberValue))
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("cannot set number value to %s", ptr.Kind())
|
||||
}
|
||||
case napi.TypeString:
|
||||
switch ptr.Kind() {
|
||||
case reflect.String:
|
||||
default:
|
||||
return fmt.Errorf("cannot set string to %s", ptr.Kind())
|
||||
}
|
||||
str, err := napi.ToString(napiValue).Utf8Value()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.Set(reflect.ValueOf(str))
|
||||
return nil
|
||||
case napi.TypeDate:
|
||||
switch ptrType.Kind() {
|
||||
case reflect.Struct:
|
||||
if ptrType == reflect.TypeFor[time.Time]() {
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
return fmt.Errorf("cannot set Date to %s", ptr.Kind())
|
||||
}
|
||||
timeDate, err := napi.ToDate(napiValue).Time()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.Set(reflect.ValueOf(timeDate))
|
||||
return nil
|
||||
case napi.TypeArray:
|
||||
napiArray := napi.ToArray(napiValue)
|
||||
size, err := napiArray.Length()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch ptr.Kind() {
|
||||
case reflect.Slice:
|
||||
value := reflect.MakeSlice(ptrType, size, size)
|
||||
for index := range size {
|
||||
napiValue, err := napiArray.Get(index)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if err = valueFrom(napiValue, value.Index(index)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ptr.Set(value)
|
||||
return nil
|
||||
case reflect.Array:
|
||||
value := reflect.New(ptrType)
|
||||
for index := range min(size, value.Len()) {
|
||||
napiValue, err := napiArray.Get(index)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if err = valueFrom(napiValue, value.Index(index)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ptr.Set(value)
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("cannot set Array to %s", ptr.Kind())
|
||||
}
|
||||
case napi.TypeBuffer:
|
||||
switch ptr.Kind() {
|
||||
case reflect.Slice:
|
||||
if ptrType == reflect.TypeFor[[]byte]() {
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
return fmt.Errorf("cannot set Buffer to %s", ptr.Kind())
|
||||
}
|
||||
buff, err := napi.ToBuffer(napiValue).Data()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ptr.SetBytes(buff)
|
||||
return nil
|
||||
case napi.TypeObject:
|
||||
obj := napi.ToObject(napiValue)
|
||||
switch ptr.Kind() {
|
||||
case reflect.Struct:
|
||||
ptr.Set(reflect.New(ptrType).Elem())
|
||||
for keyIndex := range ptrType.NumField() {
|
||||
field, fieldType := ptr.Field(keyIndex), ptrType.Field(keyIndex)
|
||||
if !fieldType.IsExported() || fieldType.Tag.Get(propertiesTagName) == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
keyName, omitEmpty, omitZero := fieldType.Name, false, false
|
||||
if strings.Count(fieldType.Tag.Get(propertiesTagName), ",") > 0 {
|
||||
fields := strings.SplitN(fieldType.Tag.Get(propertiesTagName), ",", 2)
|
||||
keyName = fields[0]
|
||||
switch fields[1] {
|
||||
case "omitempty":
|
||||
omitEmpty = true
|
||||
case "omitzero":
|
||||
omitZero = true
|
||||
}
|
||||
} else {
|
||||
omitEmpty, omitZero = true, true
|
||||
}
|
||||
|
||||
if ok, err := obj.Has(keyName); err != nil {
|
||||
return err
|
||||
} else if !ok && !(omitEmpty || omitZero) {
|
||||
return fmt.Errorf("cannot set %s to %s", keyName, ptr.Kind())
|
||||
}
|
||||
|
||||
value, err := obj.Get(keyName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
valueTypeof, _ := value.Type()
|
||||
if omitEmpty || omitZero {
|
||||
switch valueTypeof {
|
||||
case napi.TypeUndefined, napi.TypeNull, napi.TypeUnkown:
|
||||
continue
|
||||
case napi.TypeString:
|
||||
if str, _ := napi.ToString(value).Utf8Value(); str == "" {
|
||||
continue
|
||||
}
|
||||
case napi.TypeDate:
|
||||
if timeDate, _ := napi.ToDate(value).Time(); timeDate.Unix() == 0 {
|
||||
continue
|
||||
}
|
||||
case napi.TypeBigInt:
|
||||
if numberValue, _ := napi.ToBigint(value).Int64(); numberValue == 0 {
|
||||
continue
|
||||
}
|
||||
case napi.TypeNumber:
|
||||
if numberValue, _ := napi.ToNumber(value).Int(); numberValue == 0 {
|
||||
continue
|
||||
}
|
||||
case napi.TypeArray:
|
||||
if size, _ := napi.ToArray(value).Length(); size == 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
valueOf := reflect.New(fieldType.Type).Elem()
|
||||
if err := valueFrom(value, valueOf); err != nil {
|
||||
return err
|
||||
}
|
||||
field.Set(valueOf)
|
||||
}
|
||||
return nil
|
||||
case reflect.Map:
|
||||
// Check if key is string, bool, int*, uint*, float*, else return error
|
||||
switch ptrType.Key().Kind() {
|
||||
case reflect.String:
|
||||
case reflect.Bool:
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
case reflect.Float32, reflect.Float64:
|
||||
default:
|
||||
return fmt.Errorf("cannot set Object to %s", ptr.Kind())
|
||||
}
|
||||
|
||||
goMap := reflect.MakeMap(ptrType)
|
||||
for keyName, value := range obj.Seq() {
|
||||
keySetValue := reflect.New(ptrType.Key()).Elem()
|
||||
switch ptrType.Key().Kind() {
|
||||
case reflect.String:
|
||||
keySetValue.SetString(keyName)
|
||||
case reflect.Bool:
|
||||
boolV, err := strconv.ParseBool(keyName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keySetValue.SetBool(boolV)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
intV, err := strconv.ParseInt(keyName, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keySetValue.SetInt(intV)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
intV, err := strconv.ParseUint(keyName, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keySetValue.SetUint(intV)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
floatV, err := strconv.ParseFloat(keyName, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keySetValue.SetFloat(floatV)
|
||||
}
|
||||
|
||||
valueOf := reflect.New(ptrType.Elem()).Elem()
|
||||
if err := valueFrom(value, valueOf); err != nil {
|
||||
return err
|
||||
}
|
||||
goMap.SetMapIndex(keySetValue, valueOf)
|
||||
}
|
||||
ptr.Set(goMap)
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("cannot set Object to %s", ptr.Kind())
|
||||
}
|
||||
default:
|
||||
println(typeOf.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
123
js/js_func.go
Normal file
123
js/js_func.go
Normal file
@ -0,0 +1,123 @@
|
||||
package js
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go"
|
||||
internalNapi "sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi"
|
||||
)
|
||||
|
||||
// Create napi bind to golang functions
|
||||
func GoFuncOf(env napi.EnvType, function any) (napi.ValueType, error) {
|
||||
return funcOf(env, reflect.ValueOf(function))
|
||||
}
|
||||
|
||||
func funcOf(env napi.EnvType, ptr reflect.Value) (napi.ValueType, error) {
|
||||
if ptr.Kind() != reflect.Func {
|
||||
return nil, fmt.Errorf("return function to return napi value")
|
||||
}
|
||||
|
||||
funcName := runtime.FuncForPC(ptr.Pointer()).Name()
|
||||
switch v := ptr.Interface().(type) {
|
||||
case nil:
|
||||
return nil, nil
|
||||
case napi.Callback:
|
||||
return napi.CreateFunction(env, funcName, v)
|
||||
case internalNapi.Callback:
|
||||
return napi.CreateFunctionNapi(env, funcName, v)
|
||||
default:
|
||||
return napi.CreateFunction(env, funcName, func(env napi.EnvType, this napi.ValueType, args []napi.ValueType) (napi.ValueType, error) {
|
||||
fnType := ptr.Type()
|
||||
returnValues := []reflect.Value{}
|
||||
switch {
|
||||
case fnType.NumIn() == 0 && fnType.NumOut() == 0:
|
||||
returnValues = ptr.Call([]reflect.Value{})
|
||||
case !fnType.IsVariadic():
|
||||
returnValues = ptr.Call(goValuesInFunc(ptr, args, false))
|
||||
default:
|
||||
returnValues = ptr.CallSlice(goValuesInFunc(ptr, args, true))
|
||||
}
|
||||
|
||||
switch len(returnValues) {
|
||||
case 0:
|
||||
return nil, nil
|
||||
case 1:
|
||||
return valueOf(env, returnValues[0])
|
||||
default:
|
||||
lastValue := returnValues[len(returnValues)-1]
|
||||
if lastValue.CanConvert(reflect.TypeFor[error]()) {
|
||||
returnValues = returnValues[:len(returnValues)-1]
|
||||
if !lastValue.IsNil() {
|
||||
if err := lastValue.Interface().(error); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch len(returnValues) {
|
||||
case 1:
|
||||
// Return value from return
|
||||
return valueOf(env, returnValues[0])
|
||||
default:
|
||||
// Create array
|
||||
arr, err := napi.CreateArray(env, len(returnValues))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Append values to js array
|
||||
for index, value := range returnValues {
|
||||
napiValue, err := valueOf(env, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if err = arr.Set(index, napiValue); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return arr, nil
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func goValuesInFunc(ptr reflect.Value, jsArgs []napi.ValueType, variadic bool) (values []reflect.Value) {
|
||||
if variadic && (ptr.Type().NumIn()-1 > 0) && ptr.Type().NumIn()-1 < len(jsArgs) {
|
||||
panic(fmt.Errorf("require minimun %d arguments, called with %d", ptr.Type().NumIn()-1, len(jsArgs)))
|
||||
} else if !variadic &&ptr.Type().NumIn() != len(jsArgs) {
|
||||
panic(fmt.Errorf("require %d arguments, called with %d", ptr.Type().NumIn(), len(jsArgs)))
|
||||
}
|
||||
|
||||
size := ptr.Type().NumIn()
|
||||
if variadic {
|
||||
size--
|
||||
}
|
||||
|
||||
values = make([]reflect.Value, size)
|
||||
for index := range values {
|
||||
valueOf := reflect.New(ptr.Type().In(index))
|
||||
if err := valueFrom(jsArgs[index], valueOf); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
values[index] = valueOf
|
||||
}
|
||||
|
||||
if variadic {
|
||||
variadicType := ptr.Type().In(size).Elem()
|
||||
|
||||
valueAppend := jsArgs[size:]
|
||||
valueOf := reflect.MakeSlice(reflect.SliceOf(variadicType), len(valueAppend), len(valueAppend))
|
||||
for index := range valueAppend {
|
||||
if err := valueFrom(valueAppend[index], valueOf.Index(index)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
values = append(values, valueOf)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
114
number.go
Normal file
114
number.go
Normal file
@ -0,0 +1,114 @@
|
||||
package napi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi"
|
||||
)
|
||||
|
||||
type Number struct{ value }
|
||||
type Bigint struct{ value }
|
||||
|
||||
// Convert [ValueType] to [*Number]
|
||||
func ToNumber(o ValueType) *Number { return &Number{o} }
|
||||
|
||||
// Convert [ValueType] to [*Bigint]
|
||||
func ToBigint(o ValueType) *Bigint { return &Bigint{o} }
|
||||
|
||||
func (num *Number) Float() (float64, error) {
|
||||
return mustValueErr(napi.GetValueDouble(num.NapiEnv(), num.NapiValue()))
|
||||
}
|
||||
|
||||
func (num *Number) Int() (int64, error) {
|
||||
return mustValueErr(napi.GetValueInt64(num.NapiEnv(), num.NapiValue()))
|
||||
}
|
||||
|
||||
func (num *Number) Uint32() (uint32, error) {
|
||||
return mustValueErr(napi.GetValueUint32(num.NapiEnv(), num.NapiValue()))
|
||||
}
|
||||
|
||||
func (num *Number) Int32() (int32, error) {
|
||||
return mustValueErr(napi.GetValueInt32(num.NapiEnv(), num.NapiValue()))
|
||||
}
|
||||
|
||||
func (big *Bigint) Int64() (int64, error) {
|
||||
return mustValueErr2(napi.GetValueBigIntInt64(big.NapiEnv(), big.NapiValue()))
|
||||
}
|
||||
func (big *Bigint) Uint64() (uint64, error) {
|
||||
return mustValueErr2(napi.GetValueBigIntUint64(big.NapiEnv(), big.NapiValue()))
|
||||
}
|
||||
|
||||
func CreateBigint[T int64 | uint64](env EnvType, valueOf T) (*Bigint, error) {
|
||||
var value napi.Value
|
||||
var err error
|
||||
switch v := any(valueOf).(type) {
|
||||
case int64:
|
||||
if value, err = mustValueErr(napi.CreateBigIntInt64(env.NapiValue(), v)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case uint64:
|
||||
if value, err = mustValueErr(napi.CreateBigIntUint64(env.NapiValue(), v)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &Bigint{value: &Value{env: env, valueOf: value}}, nil
|
||||
}
|
||||
|
||||
func CreateNumber[T ~int | ~uint | ~int8 | ~uint8 | ~int16 | ~uint16 | ~int32 | ~uint32 | ~int64 | ~uint64 | ~float32 | ~float64](env EnvType, n T) (*Number, error) {
|
||||
var value napi.Value
|
||||
var err error
|
||||
switch v := any(n).(type) {
|
||||
case int:
|
||||
if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case uint:
|
||||
if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case int8:
|
||||
if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case uint8:
|
||||
if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case int16:
|
||||
if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case uint16:
|
||||
if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case int32:
|
||||
if value, err = mustValueErr(napi.CreateInt32(env.NapiValue(), v)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case uint32:
|
||||
if value, err = mustValueErr(napi.CreateUint32(env.NapiValue(), v)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case int64:
|
||||
if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), v)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case uint64:
|
||||
if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case float32:
|
||||
if value, err = mustValueErr(napi.CreateDouble(env.NapiValue(), float64(v))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case float64:
|
||||
if value, err = mustValueErr(napi.CreateDouble(env.NapiValue(), v)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid number type")
|
||||
}
|
||||
return ToNumber(N_APIValue(env, value)), err
|
||||
}
|
30
object.go
30
object.go
@ -1,6 +1,10 @@
|
||||
package napi
|
||||
|
||||
import "sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi"
|
||||
import (
|
||||
"iter"
|
||||
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi"
|
||||
)
|
||||
|
||||
type Object struct{ value }
|
||||
|
||||
@ -104,3 +108,27 @@ func (obj *Object) Freeze() error {
|
||||
func (obj *Object) Seal() error {
|
||||
return singleMustValueErr(napi.ObjectSeal(obj.NapiEnv(), obj.NapiValue()))
|
||||
}
|
||||
|
||||
func (obj *Object) Seq() iter.Seq2[string, ValueType] {
|
||||
keys, err := obj.GetPropertyNames()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return func(yield func(string, ValueType) bool) {
|
||||
for key := range keys.Seq() {
|
||||
value, err := obj.GetWithValue(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
keyName, err := ToString(key).Utf8Value()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if !yield(keyName, value) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
29
string.go
29
string.go
@ -1,6 +1,10 @@
|
||||
package napi
|
||||
|
||||
import "sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi"
|
||||
import (
|
||||
"unicode/utf16"
|
||||
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi"
|
||||
)
|
||||
|
||||
type String struct{ value }
|
||||
|
||||
@ -15,3 +19,26 @@ func CreateString(env EnvType, str string) (*String, error) {
|
||||
}
|
||||
return ToString(N_APIValue(env, napiString)), nil
|
||||
}
|
||||
|
||||
// Create string to utf16
|
||||
func CreateStringUtf16(env EnvType, str []rune) (*String, error) {
|
||||
napiString, err := mustValueErr(napi.CreateStringUtf16(env.NapiValue(), utf16.Encode(str)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ToString(N_APIValue(env, napiString)), nil
|
||||
}
|
||||
|
||||
// Get String value.
|
||||
func (str *String) Utf8Value() (string, error) {
|
||||
return mustValueErr(napi.GetValueStringUtf8(str.NapiEnv(), str.NapiValue()))
|
||||
}
|
||||
|
||||
// Converts a String value to a UTF-16 encoded in rune.
|
||||
func (str *String) Utf16Value() ([]rune, error) {
|
||||
valueOf, err := mustValueErr(napi.GetValueStringUtf16(str.NapiEnv(), str.NapiValue()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utf16.Decode(valueOf), nil
|
||||
}
|
Reference in New Issue
Block a user