feat: add field comments, local time zone decoding and in-value cancellation
Test / test (push) Successful in 1m32s

Assisted-by: GLM 5.3 Flash
This commit is contained in:
2026-09-22 00:44:23 +02:00
parent 71bd82a7a5
commit d18935ebc2
8 changed files with 307 additions and 11 deletions
+41 -1
View File
@@ -20,11 +20,13 @@ import (
// UnmarshalerContext destination; entry points without one leave it nil.
// nodes is the document's node index, present only when a destination can
// reach an OrderedMap and the parse built the tree its key order is read
// from.
// from. loc is the zone a local date-time is carried in when it decodes into
// a time.Time destination; nil keeps the wrapper-only default.
type decoder struct {
disallowUnknown bool
ctx context.Context
nodes nodeIndex
loc *time.Location
}
func newDecoder() *decoder { return &decoder{} }
@@ -244,6 +246,24 @@ func (d *decoder) assign(data any, dst reflect.Value) error {
return setOffsetDateTime(v, dst)
case time.Time:
return setDateTime(v, dst)
case LocalDateTime:
if dst.Type() == localDateTimeType {
dst.Set(reflect.ValueOf(v))
return nil
}
return d.setLocalTimeValue(v.Time, dst)
case LocalDate:
if dst.Type() == localDateType {
dst.Set(reflect.ValueOf(v))
return nil
}
return d.setLocalTimeValue(v.Time, dst)
case LocalTime:
if dst.Type() == localTimeType {
dst.Set(reflect.ValueOf(v))
return nil
}
return d.setLocalTimeValue(v.Time, dst)
default:
rv := reflect.ValueOf(data)
if rv.IsValid() && dst.Type() == rv.Type() {
@@ -464,6 +484,26 @@ func setDateTime(v time.Time, dst reflect.Value) error {
return nil
}
// setLocalTimeValue stores a local date-time value into a plain time.Time
// destination, which the decoder permits only when LocalTimeLocation fixed
// the zone the wall-clock value is carried in; without it the wrapper types
// are the only destinations a local kind fills, as they always have been.
func (d *decoder) setLocalTimeValue(t time.Time, dst reflect.Value) error {
if dst.Type() == timeType {
if d.loc != nil {
// A local value is a wall clock, so the zone choice relabels it
// rather than shifting the instant: 07:32 in the document is
// 07:32 in the location, not an hour later.
dst.Set(reflect.ValueOf(time.Date(
t.Year(), t.Month(), t.Day(),
t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), d.loc)))
return nil
}
return fmt.Errorf("interpres: cannot assign local date-time to time.Time; set Decoder.LocalTimeLocation to choose the zone")
}
return fmt.Errorf("interpres: cannot assign local date-time to %s", dst.Type())
}
func setBasic(dst, val reflect.Value, kind string) error {
if dst.Kind() != val.Kind() {
return fmt.Errorf("interpres: cannot assign %s to %s", kind, dst.Type())