package httpsfv

import (
	
	
	
	
	
)

// ErrInvalidBareItem is returned when a bare item is invalid.
var ErrInvalidBareItem = errors.New(
	"invalid bare item type (allowed types are bool, string, int64, float64, []byte, time.Time and Token)",
)

// assertBareItem asserts that v is a valid bare item
// according to https://httpwg.org/specs/rfc9651.html#item.
//
// v can be either:
//
// * an integer (Section 3.3.1.)
// * a decimal (Section 3.3.2.)
// * a string (Section 3.3.3.)
// * a token (Section 3.3.4.)
// * a byte sequence (Section 3.3.5.)
// * a boolean (Section 3.3.6.)
// * a date (Section 3.3.7.)
// * a display string (Section 3.3.8.)
func assertBareItem( interface{}) {
	switch .(type) {
	case bool,
		string,
		int,
		int8,
		int16,
		int32,
		int64,
		uint,
		uint8,
		uint16,
		uint32,
		uint64,
		float32,
		float64,
		[]byte,
		time.Time,
		Token,
		DisplayString:
		return
	default:
		panic(fmt.Errorf("%w: got %s", ErrInvalidBareItem, reflect.TypeOf()))
	}
}

// marshalBareItem serializes as defined in
// https://httpwg.org/specs/rfc9651.html#ser-bare-item.
func marshalBareItem( *strings.Builder,  interface{}) error {
	switch v := .(type) {
	case bool:
		return marshalBoolean(, )
	case string:
		return marshalString(, )
	case int64:
		return marshalInteger(, )
	case int, int8, int16, int32:
		return marshalInteger(, reflect.ValueOf().Int())
	case uint, uint8, uint16, uint32, uint64:
		// Casting an uint64 to an int64 is possible because the maximum allowed value is 999,999,999,999,999
		return marshalInteger(, int64(reflect.ValueOf().Uint()))
	case float32, float64:
		return marshalDecimal(, .(float64))
	case []byte:
		return marshalBinary(, )
	case time.Time:
		return marshalDate(, )
	case Token:
		return .marshalSFV()
	case DisplayString:
		return .marshalSFV()
	default:
		panic(ErrInvalidBareItem)
	}
}

// parseBareItem parses as defined in
// https://httpwg.org/specs/rfc9651.html#parse-bare-item.
func parseBareItem( *scanner) (interface{}, error) {
	if .eof() {
		return nil, &UnmarshalError{.off, ErrUnexpectedEndOfString}
	}

	 := .data[.off]
	switch  {
	case '"':
		return parseString()
	case '?':
		return parseBoolean()
	case '*':
		return parseToken()
	case ':':
		return parseBinary()
	case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
		return parseNumber()
	case '@':
		return parseDate()
	case '%':
		return parseDisplayString()
	default:
		if isAlpha() {
			return parseToken()
		}

		return nil, &UnmarshalError{.off, ErrUnrecognizedCharacter}
	}
}