Update dependencies
This commit is contained in:
187
vendor/github.com/go-json-experiment/json/arshal_time.go
generated
vendored
187
vendor/github.com/go-json-experiment/json/arshal_time.go
generated
vendored
@@ -6,6 +6,7 @@ package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"cmp"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-json-experiment/json/internal"
|
||||
"github.com/go-json-experiment/json/internal/jsonflags"
|
||||
"github.com/go-json-experiment/json/internal/jsonopts"
|
||||
"github.com/go-json-experiment/json/internal/jsonwire"
|
||||
@@ -22,12 +24,12 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
timeDurationType = reflect.TypeOf((*time.Duration)(nil)).Elem()
|
||||
timeTimeType = reflect.TypeOf((*time.Time)(nil)).Elem()
|
||||
timeDurationType = reflect.TypeFor[time.Duration]()
|
||||
timeTimeType = reflect.TypeFor[time.Time]()
|
||||
)
|
||||
|
||||
func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
||||
// Ideally, time types would implement MarshalerV2 and UnmarshalerV2,
|
||||
// Ideally, time types would implement MarshalerTo and UnmarshalerFrom,
|
||||
// but that would incur a dependency on package json from package time.
|
||||
// Given how widely used time is, it is more acceptable that we incur a
|
||||
// dependency on time from json.
|
||||
@@ -44,17 +46,20 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
||||
var m durationArshaler
|
||||
if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() {
|
||||
if !m.initFormat(mo.Format) {
|
||||
return newInvalidFormatError("marshal", t, mo.Format)
|
||||
return newInvalidFormatError(enc, t, mo)
|
||||
}
|
||||
} else if mo.Flags.Get(jsonflags.FormatTimeDurationAsNanosecond) {
|
||||
} else if mo.Flags.Get(jsonflags.FormatTimeWithLegacySemantics) {
|
||||
return marshalNano(enc, va, mo)
|
||||
}
|
||||
|
||||
// TODO(https://go.dev/issue/62121): Use reflect.Value.AssertTo.
|
||||
m.td = *va.Addr().Interface().(*time.Duration)
|
||||
k := stringOrNumberKind(!m.isNumeric() || mo.Flags.Get(jsonflags.StringifyNumbers))
|
||||
k := stringOrNumberKind(!m.isNumeric() || xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers))
|
||||
if err := xe.AppendRaw(k, true, m.appendMarshal); err != nil {
|
||||
return &SemanticError{action: "marshal", GoType: t, Err: err}
|
||||
if !isSyntacticError(err) && !export.IsIOError(err) {
|
||||
err = newMarshalErrorBefore(enc, t, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -64,12 +69,13 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
||||
var u durationArshaler
|
||||
if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() {
|
||||
if !u.initFormat(uo.Format) {
|
||||
return newInvalidFormatError("unmarshal", t, uo.Format)
|
||||
return newInvalidFormatError(dec, t, uo)
|
||||
}
|
||||
} else if uo.Flags.Get(jsonflags.FormatTimeDurationAsNanosecond) {
|
||||
} else if uo.Flags.Get(jsonflags.FormatTimeWithLegacySemantics) {
|
||||
return unmarshalNano(dec, va, uo)
|
||||
}
|
||||
|
||||
stringify := !u.isNumeric() || xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers)
|
||||
var flags jsonwire.ValueFlags
|
||||
td := va.Addr().Interface().(*time.Duration)
|
||||
val, err := xd.ReadValue(&flags)
|
||||
@@ -78,30 +84,31 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
||||
}
|
||||
switch k := val.Kind(); k {
|
||||
case 'n':
|
||||
*td = time.Duration(0)
|
||||
if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
|
||||
*td = time.Duration(0)
|
||||
}
|
||||
return nil
|
||||
case '"':
|
||||
if u.isNumeric() && !uo.Flags.Get(jsonflags.StringifyNumbers) {
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t}
|
||||
if !stringify {
|
||||
break
|
||||
}
|
||||
val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
|
||||
if err := u.unmarshal(val); err != nil {
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err}
|
||||
return newUnmarshalErrorAfter(dec, t, err)
|
||||
}
|
||||
*td = u.td
|
||||
return nil
|
||||
case '0':
|
||||
if !u.isNumeric() {
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t}
|
||||
if stringify {
|
||||
break
|
||||
}
|
||||
if err := u.unmarshal(val); err != nil {
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err}
|
||||
return newUnmarshalErrorAfter(dec, t, err)
|
||||
}
|
||||
*td = u.td
|
||||
return nil
|
||||
default:
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t}
|
||||
}
|
||||
return newUnmarshalErrorAfter(dec, t, nil)
|
||||
}
|
||||
case timeTimeType:
|
||||
fncs.nonDefault = true
|
||||
@@ -110,15 +117,21 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
||||
var m timeArshaler
|
||||
if mo.Format != "" && mo.FormatDepth == xe.Tokens.Depth() {
|
||||
if !m.initFormat(mo.Format) {
|
||||
return newInvalidFormatError("marshal", t, mo.Format)
|
||||
return newInvalidFormatError(enc, t, mo)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(https://go.dev/issue/62121): Use reflect.Value.AssertTo.
|
||||
m.tt = *va.Addr().Interface().(*time.Time)
|
||||
k := stringOrNumberKind(!m.isNumeric() || mo.Flags.Get(jsonflags.StringifyNumbers))
|
||||
k := stringOrNumberKind(!m.isNumeric() || xe.Tokens.Last.NeedObjectName() || mo.Flags.Get(jsonflags.StringifyNumbers))
|
||||
if err := xe.AppendRaw(k, !m.hasCustomFormat(), m.appendMarshal); err != nil {
|
||||
return &SemanticError{action: "marshal", GoType: t, Err: err}
|
||||
if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
|
||||
return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON") // unlike unmarshal, always wrapped
|
||||
}
|
||||
if !isSyntacticError(err) && !export.IsIOError(err) {
|
||||
err = newMarshalErrorBefore(enc, t, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -127,10 +140,13 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
||||
var u timeArshaler
|
||||
if uo.Format != "" && uo.FormatDepth == xd.Tokens.Depth() {
|
||||
if !u.initFormat(uo.Format) {
|
||||
return newInvalidFormatError("unmarshal", t, uo.Format)
|
||||
return newInvalidFormatError(dec, t, uo)
|
||||
}
|
||||
} else if uo.Flags.Get(jsonflags.FormatTimeWithLegacySemantics) {
|
||||
u.looseRFC3339 = true
|
||||
}
|
||||
|
||||
stringify := !u.isNumeric() || xd.Tokens.Last.NeedObjectName() || uo.Flags.Get(jsonflags.StringifyNumbers)
|
||||
var flags jsonwire.ValueFlags
|
||||
tt := va.Addr().Interface().(*time.Time)
|
||||
val, err := xd.ReadValue(&flags)
|
||||
@@ -139,30 +155,37 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
||||
}
|
||||
switch k := val.Kind(); k {
|
||||
case 'n':
|
||||
*tt = time.Time{}
|
||||
if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
|
||||
*tt = time.Time{}
|
||||
}
|
||||
return nil
|
||||
case '"':
|
||||
if u.isNumeric() && !uo.Flags.Get(jsonflags.StringifyNumbers) {
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t}
|
||||
if !stringify {
|
||||
break
|
||||
}
|
||||
val = jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
|
||||
if err := u.unmarshal(val); err != nil {
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err}
|
||||
if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
|
||||
return err // unlike marshal, never wrapped
|
||||
}
|
||||
return newUnmarshalErrorAfter(dec, t, err)
|
||||
}
|
||||
*tt = u.tt
|
||||
return nil
|
||||
case '0':
|
||||
if !u.isNumeric() {
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t}
|
||||
if stringify {
|
||||
break
|
||||
}
|
||||
if err := u.unmarshal(val); err != nil {
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err}
|
||||
if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
|
||||
return err // unlike marshal, never wrapped
|
||||
}
|
||||
return newUnmarshalErrorAfter(dec, t, err)
|
||||
}
|
||||
*tt = u.tt
|
||||
return nil
|
||||
default:
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t}
|
||||
}
|
||||
return newUnmarshalErrorAfter(dec, t, nil)
|
||||
}
|
||||
}
|
||||
return fncs
|
||||
@@ -175,8 +198,7 @@ type durationArshaler struct {
|
||||
// - 0 uses time.Duration.String
|
||||
// - 1e0, 1e3, 1e6, or 1e9 use a decimal encoding of the duration as
|
||||
// nanoseconds, microseconds, milliseconds, or seconds.
|
||||
// - 60 uses a "H:MM:SS.SSSSSSSSS" encoding
|
||||
base uint
|
||||
base uint64
|
||||
}
|
||||
|
||||
func (a *durationArshaler) initFormat(format string) (ok bool) {
|
||||
@@ -191,8 +213,6 @@ func (a *durationArshaler) initFormat(format string) (ok bool) {
|
||||
a.base = 1e3
|
||||
case "nano":
|
||||
a.base = 1e0
|
||||
case "base60": // see https://en.wikipedia.org/wiki/Sexagesimal#Modern_usage
|
||||
a.base = 60
|
||||
default:
|
||||
return false
|
||||
}
|
||||
@@ -207,8 +227,6 @@ func (a *durationArshaler) appendMarshal(b []byte) ([]byte, error) {
|
||||
switch a.base {
|
||||
case 0:
|
||||
return append(b, a.td.String()...), nil
|
||||
case 60:
|
||||
return appendDurationBase60(b, a.td), nil
|
||||
default:
|
||||
return appendDurationBase10(b, a.td, a.base), nil
|
||||
}
|
||||
@@ -218,8 +236,6 @@ func (a *durationArshaler) unmarshal(b []byte) (err error) {
|
||||
switch a.base {
|
||||
case 0:
|
||||
a.td, err = time.ParseDuration(string(b))
|
||||
case 60:
|
||||
a.td, err = parseDurationBase60(b)
|
||||
default:
|
||||
a.td, err = parseDurationBase10(b, a.base)
|
||||
}
|
||||
@@ -234,8 +250,10 @@ type timeArshaler struct {
|
||||
// - 1e0, 1e3, 1e6, or 1e9 use a decimal encoding of the timestamp as
|
||||
// seconds, milliseconds, microseconds, or nanoseconds since Unix epoch.
|
||||
// - math.MaxUint uses time.Time.Format to encode the timestamp
|
||||
base uint
|
||||
base uint64
|
||||
format string // time format passed to time.Parse
|
||||
|
||||
looseRFC3339 bool
|
||||
}
|
||||
|
||||
func (a *timeArshaler) initFormat(format string) bool {
|
||||
@@ -317,11 +335,7 @@ func (a *timeArshaler) hasCustomFormat() bool {
|
||||
func (a *timeArshaler) appendMarshal(b []byte) ([]byte, error) {
|
||||
switch a.base {
|
||||
case 0:
|
||||
// TODO(https://go.dev/issue/60204): Use cmp.Or(a.format, time.RFC3339Nano).
|
||||
format := a.format
|
||||
if format == "" {
|
||||
format = time.RFC3339Nano
|
||||
}
|
||||
format := cmp.Or(a.format, time.RFC3339Nano)
|
||||
n0 := len(b)
|
||||
b = a.tt.AppendFormat(b, format)
|
||||
// Not all Go timestamps can be represented as valid RFC 3339.
|
||||
@@ -360,6 +374,8 @@ func (a *timeArshaler) unmarshal(b []byte) (err error) {
|
||||
return &time.ParseError{Layout: layout, Value: value, LayoutElem: layoutElem, ValueElem: valueElem, Message: message}
|
||||
}
|
||||
switch {
|
||||
case a.looseRFC3339:
|
||||
return nil
|
||||
case b[len("2006-01-02T")+1] == ':': // hour must be two digits
|
||||
return newParseError(time.RFC3339, string(b), "15", string(b[len("2006-01-02T"):][:1]), "")
|
||||
case b[len("2006-01-02T15:04:05")] == ',': // sub-second separator must be a period
|
||||
@@ -384,16 +400,16 @@ func (a *timeArshaler) unmarshal(b []byte) (err error) {
|
||||
|
||||
// appendDurationBase10 appends d formatted as a decimal fractional number,
|
||||
// where pow10 is a power-of-10 used to scale down the number.
|
||||
func appendDurationBase10(b []byte, d time.Duration, pow10 uint) []byte {
|
||||
func appendDurationBase10(b []byte, d time.Duration, pow10 uint64) []byte {
|
||||
b, n := mayAppendDurationSign(b, d) // append sign
|
||||
whole, frac := bits.Div64(0, n, uint64(pow10)) // compute whole and frac fields
|
||||
b = strconv.AppendUint(b, whole, 10) // append whole field
|
||||
return appendFracBase10(b, uint(frac), pow10) // append frac field
|
||||
return appendFracBase10(b, frac, pow10) // append frac field
|
||||
}
|
||||
|
||||
// parseDurationBase10 parses d from a decimal fractional number,
|
||||
// where pow10 is a power-of-10 used to scale up the number.
|
||||
func parseDurationBase10(b []byte, pow10 uint) (time.Duration, error) {
|
||||
func parseDurationBase10(b []byte, pow10 uint64) (time.Duration, error) {
|
||||
suffix, neg := consumeSign(b) // consume sign
|
||||
wholeBytes, fracBytes := bytesCutByte(suffix, '.', true) // consume whole and frac fields
|
||||
whole, okWhole := jsonwire.ParseUint(wholeBytes) // parse whole field; may overflow
|
||||
@@ -410,45 +426,6 @@ func parseDurationBase10(b []byte, pow10 uint) (time.Duration, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// appendDurationBase60 appends d formatted with H:MM:SS.SSS notation.
|
||||
func appendDurationBase60(b []byte, d time.Duration) []byte {
|
||||
b, n := mayAppendDurationSign(b, d) // append sign
|
||||
n, nsec := bits.Div64(0, n, 1e9) // compute nsec field
|
||||
n, sec := bits.Div64(0, n, 60) // compute sec field
|
||||
hour, min := bits.Div64(0, n, 60) // compute hour and min fields
|
||||
b = strconv.AppendUint(b, hour, 10) // append hour field
|
||||
b = append(b, ':', '0'+byte(min/10), '0'+byte(min%10)) // append min field
|
||||
b = append(b, ':', '0'+byte(sec/10), '0'+byte(sec%10)) // append sec field
|
||||
return appendFracBase10(b, uint(nsec), 1e9) // append nsec field
|
||||
}
|
||||
|
||||
// parseDurationBase60 parses d formatted with H:MM:SS.SSS notation.
|
||||
// The exact grammar is `-?(0|[1-9][0-9]*):[0-5][0-9]:[0-5][0-9]([.][0-9]+)?`.
|
||||
func parseDurationBase60(b []byte) (time.Duration, error) {
|
||||
checkBase60 := func(b []byte) bool {
|
||||
return len(b) == 2 && ('0' <= b[0] && b[0] <= '5') && '0' <= b[1] && b[1] <= '9'
|
||||
}
|
||||
suffix, neg := consumeSign(b) // consume sign
|
||||
hourBytes, suffix := bytesCutByte(suffix, ':', false) // consume hour field
|
||||
minBytes, suffix := bytesCutByte(suffix, ':', false) // consume min field
|
||||
secBytes, nsecBytes := bytesCutByte(suffix, '.', true) // consume sec and nsec fields
|
||||
hour, okHour := jsonwire.ParseUint(hourBytes) // parse hour field; may overflow
|
||||
min := parseDec2(minBytes) // parse min field
|
||||
sec := parseDec2(secBytes) // parse sec field
|
||||
nsec, okNsec := parseFracBase10(nsecBytes, 1e9) // parse nsec field
|
||||
n := uint64(min)*60*1e9 + uint64(sec)*1e9 + uint64(nsec) // cannot overflow
|
||||
hi, lo := bits.Mul64(hour, 60*60*1e9) // overflow if hi > 0
|
||||
sum, co := bits.Add64(lo, n, 0) // overflow if co > 0
|
||||
switch d := mayApplyDurationSign(sum, neg); { // overflow if neg != (d < 0)
|
||||
case (!okHour && hour != math.MaxUint64) || !checkBase60(minBytes) || !checkBase60(secBytes) || !okNsec:
|
||||
return 0, fmt.Errorf("invalid duration %q: %w", b, strconv.ErrSyntax)
|
||||
case !okHour || hi > 0 || co > 0 || neg != (d < 0):
|
||||
return 0, fmt.Errorf("invalid duration %q: %w", b, strconv.ErrRange)
|
||||
default:
|
||||
return d, nil
|
||||
}
|
||||
}
|
||||
|
||||
// mayAppendDurationSign appends a negative sign if n is negative.
|
||||
func mayAppendDurationSign(b []byte, d time.Duration) ([]byte, uint64) {
|
||||
if d < 0 {
|
||||
@@ -469,7 +446,7 @@ func mayApplyDurationSign(n uint64, neg bool) time.Duration {
|
||||
|
||||
// appendTimeUnix appends t formatted as a decimal fractional number,
|
||||
// where pow10 is a power-of-10 used to scale up the number.
|
||||
func appendTimeUnix(b []byte, t time.Time, pow10 uint) []byte {
|
||||
func appendTimeUnix(b []byte, t time.Time, pow10 uint64) []byte {
|
||||
sec, nsec := t.Unix(), int64(t.Nanosecond())
|
||||
if sec < 0 {
|
||||
b = append(b, '-')
|
||||
@@ -478,20 +455,20 @@ func appendTimeUnix(b []byte, t time.Time, pow10 uint) []byte {
|
||||
switch {
|
||||
case pow10 == 1e0: // fast case where units is in seconds
|
||||
b = strconv.AppendUint(b, uint64(sec), 10)
|
||||
return appendFracBase10(b, uint(nsec), 1e9)
|
||||
return appendFracBase10(b, uint64(nsec), 1e9)
|
||||
case uint64(sec) < 1e9: // intermediate case where units is not seconds, but no overflow
|
||||
b = strconv.AppendUint(b, uint64(sec)*uint64(pow10)+uint64(uint(nsec)/(1e9/pow10)), 10)
|
||||
return appendFracBase10(b, (uint(nsec)*pow10)%1e9, 1e9)
|
||||
b = strconv.AppendUint(b, uint64(sec)*uint64(pow10)+uint64(uint64(nsec)/(1e9/pow10)), 10)
|
||||
return appendFracBase10(b, (uint64(nsec)*pow10)%1e9, 1e9)
|
||||
default: // slow case where units is not seconds and overflow would occur
|
||||
b = strconv.AppendUint(b, uint64(sec), 10)
|
||||
b = appendPaddedBase10(b, uint(uint(nsec)/(1e9/pow10)), pow10)
|
||||
return appendFracBase10(b, (uint(nsec)*pow10)%1e9, 1e9)
|
||||
b = appendPaddedBase10(b, uint64(nsec)/(1e9/pow10), pow10)
|
||||
return appendFracBase10(b, (uint64(nsec)*pow10)%1e9, 1e9)
|
||||
}
|
||||
}
|
||||
|
||||
// parseTimeUnix parses t formatted as a decimal fractional number,
|
||||
// where pow10 is a power-of-10 used to scale down the number.
|
||||
func parseTimeUnix(b []byte, pow10 uint) (time.Time, error) {
|
||||
func parseTimeUnix(b []byte, pow10 uint64) (time.Time, error) {
|
||||
suffix, neg := consumeSign(b) // consume sign
|
||||
wholeBytes, fracBytes := bytesCutByte(suffix, '.', true) // consume whole and frac fields
|
||||
whole, okWhole := jsonwire.ParseUint(wholeBytes) // parse whole field; may overflow
|
||||
@@ -502,14 +479,14 @@ func parseTimeUnix(b []byte, pow10 uint) (time.Time, error) {
|
||||
sec = int64(whole) // check overflow later after negation
|
||||
nsec = int64(frac) // cannot overflow
|
||||
case okWhole: // intermediate case where units is not seconds, but no overflow
|
||||
sec = int64(whole / uint64(pow10)) // check overflow later after negation
|
||||
nsec = int64((uint(whole)%pow10)*(1e9/pow10) + uint(frac)) // cannot overflow
|
||||
sec = int64(whole / pow10) // check overflow later after negation
|
||||
nsec = int64((whole%pow10)*(1e9/pow10) + frac) // cannot overflow
|
||||
case !okWhole && whole == math.MaxUint64: // slow case where units is not seconds and overflow occurred
|
||||
width := int(math.Log10(float64(pow10))) // compute len(strconv.Itoa(pow10-1))
|
||||
whole, okWhole = jsonwire.ParseUint(wholeBytes[:len(wholeBytes)-width]) // parse the upper whole field
|
||||
mid, _ := parsePaddedBase10(wholeBytes[len(wholeBytes)-width:], pow10) // parse the lower whole field
|
||||
sec = int64(whole) // check overflow later after negation
|
||||
nsec = int64(uint(mid)*(1e9/pow10) + frac) // cannot overflow
|
||||
nsec = int64(mid*(1e9/pow10) + frac) // cannot overflow
|
||||
}
|
||||
if neg {
|
||||
sec, nsec = negateSecNano(sec, nsec)
|
||||
@@ -535,7 +512,7 @@ func negateSecNano(sec, nsec int64) (int64, int64) {
|
||||
|
||||
// appendFracBase10 appends the fraction of n/max10,
|
||||
// where max10 is a power-of-10 that is larger than n.
|
||||
func appendFracBase10(b []byte, n, max10 uint) []byte {
|
||||
func appendFracBase10(b []byte, n, max10 uint64) []byte {
|
||||
if n == 0 {
|
||||
return b
|
||||
}
|
||||
@@ -544,7 +521,7 @@ func appendFracBase10(b []byte, n, max10 uint) []byte {
|
||||
|
||||
// parseFracBase10 parses the fraction of n/max10,
|
||||
// where max10 is a power-of-10 that is larger than n.
|
||||
func parseFracBase10(b []byte, max10 uint) (n uint, ok bool) {
|
||||
func parseFracBase10(b []byte, max10 uint64) (n uint64, ok bool) {
|
||||
switch {
|
||||
case len(b) == 0:
|
||||
return 0, true
|
||||
@@ -556,31 +533,31 @@ func parseFracBase10(b []byte, max10 uint) (n uint, ok bool) {
|
||||
|
||||
// appendPaddedBase10 appends a zero-padded encoding of n,
|
||||
// where max10 is a power-of-10 that is larger than n.
|
||||
func appendPaddedBase10(b []byte, n, max10 uint) []byte {
|
||||
func appendPaddedBase10(b []byte, n, max10 uint64) []byte {
|
||||
if n < max10/10 {
|
||||
// Formatting of n is shorter than log10(max10),
|
||||
// so add max10/10 to ensure the length is equal to log10(max10).
|
||||
i := len(b)
|
||||
b = strconv.AppendUint(b, uint64(n+max10/10), 10)
|
||||
b = strconv.AppendUint(b, n+max10/10, 10)
|
||||
b[i]-- // subtract the addition of max10/10
|
||||
return b
|
||||
}
|
||||
return strconv.AppendUint(b, uint64(n), 10)
|
||||
return strconv.AppendUint(b, n, 10)
|
||||
}
|
||||
|
||||
// parsePaddedBase10 parses b as the zero-padded encoding of n,
|
||||
// where max10 is a power-of-10 that is larger than n.
|
||||
// Truncated suffix is treated as implicit zeros.
|
||||
// Extended suffix is ignored, but verified to contain only digits.
|
||||
func parsePaddedBase10(b []byte, max10 uint) (n uint, ok bool) {
|
||||
pow10 := uint(1)
|
||||
func parsePaddedBase10(b []byte, max10 uint64) (n uint64, ok bool) {
|
||||
pow10 := uint64(1)
|
||||
for pow10 < max10 {
|
||||
n *= 10
|
||||
if len(b) > 0 {
|
||||
if b[0] < '0' || '9' < b[0] {
|
||||
return n, false
|
||||
}
|
||||
n += uint(b[0] - '0')
|
||||
n += uint64(b[0] - '0')
|
||||
b = b[1:]
|
||||
}
|
||||
pow10 *= 10
|
||||
|
||||
Reference in New Issue
Block a user