Files
qgo-server/vendor/github.com/dunglas/httpsfv/integer.go
Smile Rex 6ace91a21a
All checks were successful
Create and publish a Docker image 🚀 / build-and-push-image (push) Successful in 1m49s
add vendor data
2026-03-10 01:11:41 +03:00

121 lines
2.2 KiB
Go

package httpsfv
import (
"errors"
"io"
"strconv"
)
const maxDigit = 12
// ErrNotDigit is returned when a character should be a digit but isn't.
var ErrNotDigit = errors.New("character is not a digit")
// ErrNumberOutOfRange is returned when the number is too large according to the specification.
var ErrNumberOutOfRange = errors.New("integer or decimal out of range")
// ErrInvalidDecimalFormat is returned when the decimal format is invalid.
var ErrInvalidDecimalFormat = errors.New("invalid decimal format")
const (
typeInteger = iota
typeDecimal
)
// marshalInteger serializes as defined in
// https://httpwg.org/specs/rfc9651.html#integer.
func marshalInteger(b io.StringWriter, i int64) error {
if i < -999999999999999 || i > 999999999999999 {
return ErrNumberOutOfRange
}
_, err := b.WriteString(strconv.FormatInt(i, 10))
return err
}
// parseNumber parses as defined in
// https://httpwg.org/specs/rfc9651.html#parse-number.
func parseNumber(s *scanner) (interface{}, error) {
neg := isNeg(s)
if neg && s.eof() {
return 0, &UnmarshalError{s.off, ErrUnexpectedEndOfString}
}
if !isDigit(s.data[s.off]) {
return 0, &UnmarshalError{s.off, ErrNotDigit}
}
start := s.off
s.off++
var (
decSepOff int
t = typeInteger
)
for s.off < len(s.data) {
size := s.off - start
if (t == typeInteger && (size >= 15)) || size >= 16 {
return 0, &UnmarshalError{s.off, ErrNumberOutOfRange}
}
c := s.data[s.off]
if isDigit(c) {
s.off++
continue
}
if t == typeInteger && c == '.' {
if size > maxDigit {
return 0, &UnmarshalError{s.off, ErrNumberOutOfRange}
}
t = typeDecimal
decSepOff = s.off
s.off++
continue
}
break
}
str := s.data[start:s.off]
if t == typeInteger {
return parseInteger(str, neg, s.off)
}
return parseDecimal(s, decSepOff, str, neg)
}
func isNeg(s *scanner) bool {
if s.data[s.off] == '-' {
s.off++
return true
}
return false
}
func parseInteger(str string, neg bool, off int) (int64, error) {
i, err := strconv.ParseInt(str, 10, 64)
if err != nil {
// Should never happen
return 0, &UnmarshalError{off, err}
}
if neg {
i = -i
}
if i < -999999999999999 || i > 999999999999999 {
return 0, &UnmarshalError{off, ErrNumberOutOfRange}
}
return i, err
}