package httpsfv

import (
	
	
	
)

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( io.StringWriter,  int64) error {
	if  < -999999999999999 ||  > 999999999999999 {
		return ErrNumberOutOfRange
	}

	,  := .WriteString(strconv.FormatInt(, 10))

	return 
}

// parseNumber parses as defined in
// https://httpwg.org/specs/rfc9651.html#parse-number.
func parseNumber( *scanner) (interface{}, error) {
	 := isNeg()
	if  && .eof() {
		return 0, &UnmarshalError{.off, ErrUnexpectedEndOfString}
	}

	if !isDigit(.data[.off]) {
		return 0, &UnmarshalError{.off, ErrNotDigit}
	}

	 := .off
	.off++

	var (
		 int
		         = typeInteger
	)

	for .off < len(.data) {
		 := .off - 
		if ( == typeInteger && ( >= 15)) ||  >= 16 {
			return 0, &UnmarshalError{.off, ErrNumberOutOfRange}
		}

		 := .data[.off]
		if isDigit() {
			.off++

			continue
		}

		if  == typeInteger &&  == '.' {
			if  > maxDigit {
				return 0, &UnmarshalError{.off, ErrNumberOutOfRange}
			}

			 = typeDecimal
			 = .off
			.off++

			continue
		}

		break
	}

	 := .data[:.off]

	if  == typeInteger {
		return parseInteger(, , .off)
	}

	return parseDecimal(, , , )
}

func isNeg( *scanner) bool {
	if .data[.off] == '-' {
		.off++

		return true
	}

	return false
}

func parseInteger( string,  bool,  int) (int64, error) {
	,  := strconv.ParseInt(, 10, 64)
	if  != nil {
		// Should never happen
		return 0, &UnmarshalError{, }
	}

	if  {
		 = -
	}

	if  < -999999999999999 ||  > 999999999999999 {
		return 0, &UnmarshalError{, ErrNumberOutOfRange}
	}

	return , 
}