package conf import ( "fmt" "strconv" "strings" "time" ) const defaultOverTime = time.Hour const ( BurstRateType = "burst" IntervalRateType = "interval" ) type Rate struct { Events float64 `json:"events,omitempty"` OverTime time.Duration `json:"over_time,omitempty"` typ string } func (r *Rate) GetRateType() string { if r.typ == "" { return IntervalRateType } return r.typ } // Decode is used by envconfig to parse the env-config string to a Rate value. func (r *Rate) Decode(value string) error { if f, err := strconv.ParseFloat(value, 64); err == nil { r.typ = IntervalRateType r.Events = f r.OverTime = defaultOverTime return nil } parts := strings.Split(value, "/") if len(parts) != 2 { return fmt.Errorf("rate: value does not match rate syntax %q", value) } // 52 because the uint needs to fit in a float64 e, err := strconv.ParseUint(parts[0], 10, 52) if err != nil { return fmt.Errorf("rate: events part of rate value %q failed to parse as uint64: %w", value, err) } d, err := time.ParseDuration(parts[1]) if err != nil { return fmt.Errorf("rate: over-time part of rate value %q failed to parse as duration: %w", value, err) } r.typ = BurstRateType r.Events = float64(e) r.OverTime = d return nil } func (r *Rate) String() string { if r.OverTime == 0 { return fmt.Sprintf("%f", r.Events) } return fmt.Sprintf("%d/%s", uint64(r.Events), r.OverTime.String()) }