finally support blobs (go->ts as arg and return)

This commit is contained in:
Egor Aristov 2025-11-16 11:55:04 +03:00
parent 0e6a217c14
commit d61e3d7aa6
Signed by: egor3f
GPG Key ID: 40482A264AAEC85F
7 changed files with 65 additions and 26 deletions

View File

@ -22,10 +22,9 @@ async function main() {
console.log(`call result ts->go Div = ${await remoteApi.Div(10, 2)}`);
// todo check empty array
const data1 = new Uint8Array(100).fill(0b10101010, 0, 100);
const data2 = new Uint8Array(100).fill(0b11110000, 0, 100);
console.log(`call result ts->go XorData = ${await remoteApi.XorData(data1, data2)}`);
const data1 = Buffer.alloc(10, 0b10101010);
const data2 = Buffer.alloc(10, 0b11110000);
console.log(`call result ts->go XorData = ${(await remoteApi.XorData(data1, data2)).toString('hex')}`);
await ipc.wait();
}

View File

@ -1,6 +1,7 @@
// Code generated by kitcom. DO NOT EDIT.
import { ParentIPC, ChildIPC } from "kitten-ipc";
export default class GoIpcApi {
protected ipc: ParentIPC | ChildIPC;
@ -13,8 +14,9 @@ export default class GoIpcApi {
return results[0] as number;
}
async XorData(data1: Uint8Array, data2: Uint8Array): Promise<Uint8Array> {
async XorData(data1: Buffer, data2: Buffer): Promise<Buffer> {
const results = await this.ipc.call("GoIpcApi.XorData", data1, data2);
return results[0] as Uint8Array;
results[0] = Buffer.from(results[0], "base64");
return results[0] as Buffer;
}
}

View File

@ -13,6 +13,23 @@ const (
TArray ValType = 5
)
func (v ValType) String() string {
switch v {
case TInt:
return "int"
case TString:
return "string"
case TBool:
return "bool"
case TBlob:
return "blob"
case TArray:
return "array"
default:
panic("unreachable code")
}
}
type Val struct {
Name string
Type ValType

View File

@ -35,7 +35,7 @@ func (g *TypescriptApiGenerator) Generate(apis *api.Api, destFile string) error
api.TInt: "number",
api.TString: "string",
api.TBool: "boolean",
api.TBlob: "Uint8Array",
api.TBlob: "Buffer",
}[t]
if !ok {
return "", fmt.Errorf("cannot generate type %v", t)

View File

@ -1,25 +1,31 @@
{{- /*gotype: efprojects.com/kitten-ipc/kitcom/internal/ts.tsGenData*/ -}}
// Code generated by kitcom. DO NOT EDIT.
import {ParentIPC, ChildIPC} from 'kitten-ipc';
{{- /*gotype: efprojects.com/kitten-ipc/kitcom/ts.tsGenData*/ -}}
{{range $e := .Api.Endpoints}}
export default class {{$e.Name}} {
{{ range $e := .Api.Endpoints }}
export default class {{ $e.Name }} {
protected ipc: ParentIPC | ChildIPC;
constructor(ipc: ParentIPC | ChildIPC) {
this.ipc = ipc;
}
{{range $mtd := $e.Methods}}
{{ range $mtd := $e.Methods }}
async {{ $mtd.Name }}(
{{ range $par := $mtd.Params }}{{$par.Name}}: {{$par.Type | typedef }}, {{end}}
): Promise<{{if len $mtd.Ret}}{{(index $mtd.Ret 0).Type | typedef }}{{else}}void{{end}}> {
const results = await this.ipc.call('{{$e.Name}}.{{$mtd.Name}}',
{{range $par := $mtd.Params}}{{$par.Name}}, {{end}}
{{ range $par := $mtd.Params }}{{ $par.Name }}: {{ $par.Type | typedef }}, {{ end }}
): Promise<{{ if len $mtd.Ret }}{{ (index $mtd.Ret 0).Type | typedef }}{{ else }}void{{ end }}> {
const results = await this.ipc.call('{{ $e.Name }}.{{ $mtd.Name }}',
{{ range $par := $mtd.Params }}{{ $par.Name }}, {{ end }}
);
return {{range $i, $ret := $mtd.Ret}}{{if $i}}, {{end}}results[{{$i}}] as {{$ret.Type | typedef}}{{end}}
{{- if eq (index $mtd.Ret 0).Type.String "blob" -}}
results[0] = Buffer.from(results[0], 'base64');
{{- end -}}
return {{ range $i, $ret := $mtd.Ret }}{{ if $i }}, {{ end }}results[{{ $i }}] as {{ $ret.Type | typedef }}{{ end }}
}
{{end}}
{{ end }}
}
{{end}}
{{ end }}

View File

@ -2,6 +2,7 @@ package golang
import (
"bufio"
"encoding/base64"
"encoding/json"
"errors"
"flag"
@ -154,13 +155,27 @@ func (ipc *ipcCommon) handleCall(msg Message) {
}
func (ipc *ipcCommon) convType(needType reflect.Type, gotType reflect.Type, arg any) any {
switch needType.Kind() {
case reflect.Int:
// JSON decodes any number to float64. If we need int, we should check and convert
if needType.Kind() == reflect.Int && gotType.Kind() == reflect.Float64 {
if gotType.Kind() == reflect.Float64 {
floatArg := arg.(float64)
if float64(int64(floatArg)) == floatArg && !needType.OverflowInt(int64(floatArg)) {
arg = int(floatArg)
}
}
case reflect.Slice:
switch needType.Elem().Kind() {
case reflect.Uint8:
if gotType.Kind() == reflect.String {
var err error
arg, err = base64.StdEncoding.DecodeString(arg.(string))
if err != nil {
panic(fmt.Sprintf("decode base64: %s", err))
}
}
}
}
return arg
}

View File

@ -200,8 +200,8 @@ abstract class IPCCommon {
return arg;
// @ts-expect-error TS7029
case 'object':
if(arg instanceof Uint8Array) {
return Buffer.from(arg).toString('base64');
if(arg instanceof Buffer) {
return arg.toString('base64');
}
default:
throw new Error(`arg type ${typeof arg} is not supported`);