evcc-io/util/encode/encode.go

67 lines
1.2 KiB
Go

package encode
import (
"fmt"
"math"
"time"
)
type encoder struct {
withDuration bool
}
type Encoder interface {
Encode(v any) any
}
type EncoderOption func(*encoder)
// NewEncoder creates a new encoder with the following default conversions:
// - float NaN/Inf are converted to nil
// - zero time.Time are converted to nil
// - durations are converted to seconds using WithDuration()
// - fmt.Stringer are converted to string
// - time.Time are converted to RFC3339 string
func NewEncoder(opt ...EncoderOption) Encoder {
res := new(encoder)
for _, o := range opt {
o(res)
}
return res
}
func WithDuration() EncoderOption {
return func(e *encoder) {
e.withDuration = true
}
}
// Encode provides a consumer-friendly default encoding for any type
func (e encoder) Encode(v any) any {
switch val := v.(type) {
case time.Time:
if val.IsZero() {
return nil
}
return val.Format(time.RFC3339)
case time.Duration:
// must be before stringer to convert to seconds instead of string
if e.withDuration {
return int(val.Seconds())
}
return val
case float64:
if math.IsNaN(val) || math.IsInf(val, 0) {
return nil
}
return math.Round(val*1e3) / 1e3
case fmt.Stringer:
return val.String()
default:
return val
}
}