From 11684671f959416f893fdff927cd8de58e973a7a Mon Sep 17 00:00:00 2001 From: iyear Date: Fri, 14 Apr 2023 06:43:33 +0800 Subject: [PATCH] ports/go: support buffer type (#422) --- source/ports/go_port/source/go_port.go | 56 ++++++++++++++------- source/ports/go_port/source/go_port_test.go | 5 ++ 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/source/ports/go_port/source/go_port.go b/source/ports/go_port/source/go_port.go index caba92782..dca5e08e9 100644 --- a/source/ports/go_port/source/go_port.go +++ b/source/ports/go_port/source/go_port.go @@ -47,6 +47,7 @@ extern void *rejectCgo(void *, void *); import "C" import ( + "bytes" "errors" "fmt" "reflect" @@ -432,6 +433,16 @@ func goToValue(arg interface{}, ptr *unsafe.Pointer) { return } + if buf, ok := arg.(bytes.Buffer); ok { + str := buf.String() + p := unsafe.Pointer(C.CString(str)) + defer C.free(p) + + *ptr = C.metacall_value_create_buffer(p, (C.size_t)(len(str))) + + return + } + // Create array v := reflect.ValueOf(arg) if v.Kind() == reflect.Slice || v.Kind() == reflect.Array { @@ -460,29 +471,29 @@ func goToValue(arg interface{}, ptr *unsafe.Pointer) { /* - // Create map - if v.Kind() == reflect.Map { - length := v.Len() - *ptr = C.metacall_value_create_map(nil, (C.size_t)(length)) - cArgs := C.metacall_value_to_map(*ptr) + // Create map + if v.Kind() == reflect.Map { + length := v.Len() + *ptr = C.metacall_value_create_map(nil, (C.size_t)(length)) + cArgs := C.metacall_value_to_map(*ptr) - for index, m := 0, v.MapRange(); m.Next(); index++ { - // Access to current element of the map - mapIndex := unsafe.Pointer(uintptr(unsafe.Pointer(cArgs))+uintptr(index)*PtrSizeInBytes) + for index, m := 0, v.MapRange(); m.Next(); index++ { + // Access to current element of the map + mapIndex := unsafe.Pointer(uintptr(unsafe.Pointer(cArgs))+uintptr(index)*PtrSizeInBytes) - // Get the map pair - array := C.metacall_value_to_array(mapIndex) + // Get the map pair + array := C.metacall_value_to_array(mapIndex) - // Transform the key - key := (*unsafe.Pointer)(unsafe.Pointer(uintptr(unsafe.Pointer(array))+uintptr(0)*PtrSizeInBytes)) - goToValue(m.Key(), key) + // Transform the key + key := (*unsafe.Pointer)(unsafe.Pointer(uintptr(unsafe.Pointer(array))+uintptr(0)*PtrSizeInBytes)) + goToValue(m.Key(), key) - // Transform the value - val := (*unsafe.Pointer)(unsafe.Pointer(uintptr(unsafe.Pointer(array))+uintptr(1)*PtrSizeInBytes)) - goToValue(m.Value(), val) + // Transform the value + val := (*unsafe.Pointer)(unsafe.Pointer(uintptr(unsafe.Pointer(array))+uintptr(1)*PtrSizeInBytes)) + goToValue(m.Value(), val) + } + return } - return - } */ @@ -531,6 +542,15 @@ func valueToGo(value unsafe.Pointer) interface{} { { return C.GoString(C.metacall_value_to_string(value)) } + case C.METACALL_BUFFER: + { + buffer := C.metacall_value_to_buffer(value) + size := C.metacall_value_size(value) + + b := *bytes.NewBuffer(C.GoBytes(buffer, C.int(size))) + + return b + } case C.METACALL_ARRAY: { arrayValue := C.metacall_value_to_array(value) diff --git a/source/ports/go_port/source/go_port_test.go b/source/ports/go_port/source/go_port_test.go index 0422dd167..5fa75ff3b 100644 --- a/source/ports/go_port/source/go_port_test.go +++ b/source/ports/go_port/source/go_port_test.go @@ -1,6 +1,7 @@ package metacall import ( + "bytes" "log" "os" "reflect" @@ -153,6 +154,10 @@ func TestValues(t *testing.T) { {"double_min", float64(2.3e-308), float64(2.3e-308)}, {"double_max", float64(1.7e+308), float64(1.7e+308)}, {"string", "hello", "hello"}, + {"buffer_empty", *bytes.NewBuffer([]byte{}), *bytes.NewBuffer([]byte{})}, + {"buffer_nil", *bytes.NewBuffer(nil), *bytes.NewBuffer([]byte{})}, // TODO(iyear): how to handle nil buffer? + {"buffer_ascii", *bytes.NewBuffer([]byte{'A', 'B', 'C'}), *bytes.NewBuffer([]byte{'A', 'B', 'C'})}, + {"buffer_unicode", *bytes.NewBuffer([]byte("\u00A9\u00A9\u00A9")), *bytes.NewBuffer([]byte("\u00A9\u00A9\u00A9"))}, {"array", [3]interface{}{1, 2, 3}, []interface{}{1, 2, 3}}, {"array_bool", [3]bool{true, false, true}, []interface{}{true, false, true}}, {"array_char", [3]byte{'1', '2', '3'}, []interface{}{byte('1'), byte('2'), byte('3')}},