bytecodealliance / bytecodealliance/go-modules

wit/bindgen: support JSON encoding of WIT types

Abierto
#239 15 comentarios 0 reacciones 1 asignado Reclamado por @lxfontes Ver en GitHub
enhancement
Lenguaje dominante
Go
Estrellas
148
Forks
20
Métricas de merge de PR
Sin PR fusionados en 30 d

Descripción

This started in https://github.com/bytecodealliance/go-modules/pull/225

Goal: JSON Serialize / Deserialize WIT Records based on WIT field names.

## Progress
- [x] `record` - #265
- [x] `list` - #266
- [ ] `enum`
- [ ] `tuple`
- [ ] `variant`
- [ ] `result`
- [ ] `option`
- [ ] `resource` handle types (decide behavior)
- [ ] `error-context`
- [ ] `stream`
- [ ] `future`

# Approach

Centralize JSON serialization in the `cm` package, keeping codegen changes to a minimum.

Given a complex record type:
```
record response {
headers: list>>,
http-code: u16,
body: response-body
}
variant response-body {
ok(list),
err(function-error),
platform-err(platform-error)
}
record list-element {
optional-int: option,
optional-bool: option,
}
record function-error {
error: string
}
record platform-error {
code: string,
message: string
}
```

and filling it up:

```go
hdrVals := cm.ToList([]string{"value1", "value2"})
hdrTuple := cm.Tuple[string, cm.List[string]]{
F0: "header-name",
F1: hdrVals,
}
headers := cm.ToList([]cm.Tuple[string, cm.List[string]]{hdrTuple})
v := somefunctioninterface.Response{
Headers: headers,
HTTPCode: 200,
Body: somefunctioninterface.ResponseBodyErr(somefunctioninterface.FunctionError{Error: "failed"}),
}
```

We should serialize it to JSON as:

```
{"headers":[["header-name",["value1","value2"]]],"http-code":200,"body":{"err":{"error":"failed"}}}
```

For comparison, this is what is produced today:
```
{"Headers":{},"Body":{"RequiredParam":"required","OptionalParam":{}}}
```

# Type encoding

Whenever possible, reuse standard mappings. string -> string, u32 -> uint32, etc.

## Tuple handling
Tuples are encoded as json arrays with explicit `null`s.
```
Tuple[string,int] -> [ "some string", 42 ]
Tuple3[string, *string, int] -> [ "some string", null, 42 ]
```

## Variant handling
Variants are encoded as json dictionaries, so they can carry the variant data.

```
record somerecord {
myvariant: somevar,
}
variant somevar {
ok,
err(string),
}

// JSON
{ "myvariant": { "ok": true }}
{ "myvariant": { "error": "error value" }}
```

## Option handling
Options rely on explicit `null` for the "None" case.
```
{ "myoptional": null } // cm.None
{ "myoptional": "this" } // cm.Option[string]
```

# Questions

## Zero Value Variants

Today they end up with `tag = 0`, this impacts de-serialization of variants. We need the ability to distinct between:

- `var v Variant`
- `v := NewVariantWithZeroTagValue()`
- ` v := Some(NewVariantWithZeroTagValue)`

atm only the `Some()` path de-serializes correctly ( pointers ).

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.