Files

78 lines
2.0 KiB
Go
Raw Permalink Normal View History

package common
import (
"bytes"
"encoding/base64"
"encoding/json"
)
// wireBytes decodes a byte field as the library serialises it, which is not
// base64. A seq[byte] is rendered by Nim's std/json, whose default is an array
// of integers, so "hello" arrives as [104,101,108,108,111].
//
// Base64 strings and null decode too, so the day the library normalises its
// encodings this keeps working instead of silently dropping every payload.
type wireBytes []byte
func (b *wireBytes) UnmarshalJSON(data []byte) error {
if len(data) == 0 || string(data) == "null" {
*b = nil
return nil
}
if data[0] == '[' {
// Not []byte: encoding/json reads that from a base64 string only.
var nums []int
if err := json.Unmarshal(data, &nums); err != nil {
return err
}
out := make([]byte, len(nums))
for i, n := range nums {
out[i] = byte(n)
}
*b = out
return nil
}
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
decoded, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return err
}
*b = decoded
return nil
}
// optHasField is the discriminant Nim's std/json emits for a results.Opt[T]:
// the variant object's two private fields, rather than the value or null.
const optHasField = `"oResultPrivate"`
// unwrapOpt reduces an Opt[T] document to the value it holds, reporting false
// when the Opt is empty. A document that is already the bare value passes
// through unchanged, so this keeps working if the library ever serialises Opt
// as the value itself.
func unwrapOpt(data []byte) (json.RawMessage, bool) {
trimmed := bytes.TrimSpace(data)
if len(trimmed) == 0 || string(trimmed) == "null" {
return nil, false
}
if trimmed[0] != '{' || !bytes.Contains(trimmed, []byte(optHasField)) {
return trimmed, true
}
var opt struct {
Has bool `json:"oResultPrivate"`
Value json.RawMessage `json:"vResultPrivate"`
}
if err := json.Unmarshal(trimmed, &opt); err != nil {
return nil, false
}
if !opt.Has || len(opt.Value) == 0 {
return nil, false
}
return opt.Value, true
}