Files
promptkit/json.go

111 lines
2.9 KiB
Go

package promptkit
import (
"encoding/json"
"fmt"
"math"
"time"
)
const (
minDurationMilliseconds = int64(time.Duration(math.MinInt64) / time.Millisecond)
maxDurationMilliseconds = int64(time.Duration(math.MaxInt64) / time.Millisecond)
)
// MarshalJSON implements json.Marshaler for PreparedRun. It uses RFC 3339
// timestamps, integer duration_ms, and omits zero timing values.
func (r PreparedRun) MarshalJSON() ([]byte, error) {
var startTime, endTime *time.Time
if !r.StartTime.IsZero() {
startTime = &r.StartTime
}
if !r.EndTime.IsZero() {
endTime = &r.EndTime
}
var durationMS *int64
if r.DurationMS != 0 {
durationMS = &r.DurationMS
}
return json.Marshal(preparedRunJSON{
preparedRunJSONFields: preparedRunJSONFields(r),
StartTime: startTime,
EndTime: endTime,
DurationMS: durationMS,
})
}
// MarshalJSON implements json.Marshaler for RunResult. It encodes Duration as
// integer milliseconds in duration_ms and omits zero timing values.
func (r RunResult) MarshalJSON() ([]byte, error) {
var startTime, endTime *time.Time
if !r.StartTime.IsZero() {
startTime = &r.StartTime
}
if !r.EndTime.IsZero() {
endTime = &r.EndTime
}
var durationMS *int64
if r.Duration != 0 {
value := r.Duration.Milliseconds()
durationMS = &value
}
return json.Marshal(runResultJSON{
runResultJSONFields: runResultJSONFields(r),
StartTime: startTime,
EndTime: endTime,
DurationMS: durationMS,
})
}
// UnmarshalJSON implements json.Unmarshaler for RunResult. It decodes
// duration_ms into Duration with millisecond precision. A duration_ms outside
// the range representable by time.Duration returns an error without changing
// the receiver.
func (r *RunResult) UnmarshalJSON(data []byte) error {
var wire runResultJSON
if err := json.Unmarshal(data, &wire); err != nil {
return err
}
result := RunResult(wire.runResultJSONFields)
if wire.DurationMS != nil {
if *wire.DurationMS < minDurationMilliseconds || *wire.DurationMS > maxDurationMilliseconds {
return fmt.Errorf(
"decode RunResult duration_ms: %d cannot be represented as time.Duration",
*wire.DurationMS,
)
}
result.Duration = time.Duration(*wire.DurationMS) * time.Millisecond
}
if wire.StartTime != nil {
result.StartTime = *wire.StartTime
}
if wire.EndTime != nil {
result.EndTime = *wire.EndTime
}
*r = result
return nil
}
type preparedRunJSONFields PreparedRun
type preparedRunJSON struct {
preparedRunJSONFields
StartTime *time.Time `json:"start_time,omitempty"`
EndTime *time.Time `json:"end_time,omitempty"`
DurationMS *int64 `json:"duration_ms,omitempty"`
}
type runResultJSONFields RunResult
type runResultJSON struct {
runResultJSONFields
StartTime *time.Time `json:"start_time,omitempty"`
EndTime *time.Time `json:"end_time,omitempty"`
DurationMS *int64 `json:"duration_ms,omitempty"`
}