예제 #1
0
파일: swift.go 프로젝트: vanadium/go.swift
func doFinish(call rpc.ClientCall, numResults int) (C.SwiftByteArrayArray, error) {
	// Have all the results be decoded into *vdl.Value.
	resultPtrs := make([]interface{}, numResults)
	for i := 0; i < numResults; i++ {
		value := new(vdl.Value)
		resultPtrs[i] = &value
	}
	if err := call.Finish(resultPtrs...); err != nil {
		// Invocation error.
		return EmptySwiftByteArrayArray(), err
	}

	// VOM-encode the results. Note in the future we'll want a pathway where we can get the original VOM results
	// from finish so we don't end up wasting CPU & memory here.

	// Prepare the byte array array that can be accessed from Swift via C.malloc
	vomResultsMemory := C.malloc(C.size_t(numResults * int(C.sizeofSwiftByteArray)))
	// Make that malloc'd memory available as a slice to Go.
	vomResultsPtrsHdr := reflect.SliceHeader{
		Data: uintptr(vomResultsMemory),
		Len:  numResults,
		Cap:  numResults,
	}
	vomResults := *(*[]C.SwiftByteArray)(unsafe.Pointer(&vomResultsPtrsHdr))
	// Create the C Struct to return that encapsulates our byte array array
	var cVomResults C.SwiftByteArrayArray
	cVomResults.length = C._GoUint64(numResults)
	cVomResults.data = (*C.SwiftByteArray)(vomResultsMemory)

	// For each result, VOM encode into a byte array that we stick into the returned struct
	for i, resultPtr := range resultPtrs {
		// Remove the pointer from the result.  Simply *resultPtr doesn't work
		// as resultPtr is of type interface{}.
		result := interface{}(sutil.DerefOrDie(resultPtr))
		var vomResult []byte
		var err error
		if vomResult, err = vom.Encode(result); err != nil {
			return EmptySwiftByteArrayArray(), err
		}
		cVomResultCopy := C.malloc(C.size_t(len(vomResult)))
		C.memcpy(cVomResultCopy, unsafe.Pointer(&vomResult[0]), C.size_t(len(vomResult)))
		var cVomResult C.SwiftByteArray
		cVomResult.length = C._GoUint64(len(vomResult))
		cVomResult.data = cVomResultCopy
		vomResults[i] = cVomResult
	}
	return cVomResults, nil
}
예제 #2
0
파일: util.go 프로젝트: vanadium/go.swift
func swiftBytesCopy(data []byte) C.SwiftByteArray {
	var a C.SwiftByteArray
	a.length = C._GoUint64(len(data))
	a.data = C.malloc(C.size_t(len(data)))
	if a.data == nil {
		panic(fmt.Errorf("Unable to allocate %d bytes", a.length))
	}
	C.memmove(a.data, unsafe.Pointer(&data[0]), C.size_t(len(data)))
	return a
}
예제 #3
0
파일: type.go 프로젝트: vanadium/go.swift
//export swift_io_v_swift_impl_util_type_nativeBase64UrlDecode
func swift_io_v_swift_impl_util_type_nativeBase64UrlDecode(base64UrlEncoded *C.char) C.SwiftByteArray {
	// Decode the base64 url encoded string to bytes in a way that prevents extra copies along the CGO boundary.
	urlEncoded := C.GoString(base64UrlEncoded)
	maxLength := base64.URLEncoding.DecodedLen(len(urlEncoded))
	bytesBacking := C.malloc(C.size_t(maxLength))
	if bytesBacking == nil {
		vlog.Errorf("Unable allocate %v bytes", maxLength)
		return EmptySwiftByteArray()
	}
	var bytes []byte = (*[1 << 30]byte)(unsafe.Pointer(bytesBacking))[:maxLength:maxLength]
	n, err := base64.URLEncoding.Decode(bytes, []byte(urlEncoded))
	if err != nil {
		vlog.Errorf("Unable to base64 decode string: %v\n", err)
		C.free(bytesBacking)
		return EmptySwiftByteArray()
	}
	var swiftArray C.SwiftByteArray
	swiftArray.length = C._GoUint64(n)
	swiftArray.data = bytesBacking
	return swiftArray
}