GALA-E0050 — codec field type has no encoding

When it fires. A codec is requested — json.Codec[T], yaml.Codec[T] or StructMeta[T]() — for a struct that has a field (directly, or in a struct it nests) whose type the codec cannot serialize, or for a T that is itself one of the shapes below:

Minimal repro.

package main

import "martianoff/gala/json"

struct Job(Name string, Run func() int)

func main() {
    val codec = json.Codec[Job](json.AsIs())
    Println(codec.Encode(Job("build", () => 1)))
}

Error output.

error[GALA-E0050]: cannot generate a codec for Job: field Job.Run has type func() int: functions have no serialized form
  --> main.gala:8:33
  |
8 |     val codec = json.Codec[Job](json.AsIs())
  |                                 ^^^^ a codec field can be a string, bool, rune, int/uint/float ki…
  |
  = hint: a codec field can be a string, bool, rune, int/uint/float kind, an alias or named type over one, a struct, or an Option, Array, List or HashMap[string, _] of those

Fix. Keep only data in the struct you serialize. Store what the function would compute, or a value that names it:

struct Job(Name string, Command string)

For the other shapes: store the value instead of a pointer; use Array, List or HashMap[string, V] instead of a Go slice or map; key a map by the string form of its key; and flatten Option[Option[T]] into a sealed status you encode as a string field.

What the codec does support. Every scalar kind — string, bool, rune, int, int8…int64, uint, uint8…uint64, uintptr, byte, float32, float64 — plus aliases and Go named types over them (type Millis int64, time.Duration); structs; and Option, Array, List and HashMap[string, V] of any of these, nested to any depth.

On decode, an integer that does not fit the field’s kind (300 into an int8, -1 into a uint) and a float that overflows float32 are decode errors, not wrapped values. JSON has no spelling for NaN or ±Infinity, so encoding one fails; YAML writes them as .nan, .inf and -.inf and reads them back.

Rationale. A field the codec had no encoding for used to be written as null and skipped on decode, so Encode succeeded, Decode succeeded, and the value came back as zero. Data was lost with no signal. Rejecting the shape where the codec is requested turns that into an error you see while building.