package httpsfv

import (
	
	
	
	
	
)

type DisplayString string

var ErrInvalidDisplayString = errors.New("invalid display string type")

var notVcharOrSp = &unicode.RangeTable{
	R16: []unicode.Range16{
		{0x0000, 0x001f, 1},
		{0x007f, 0x00ff, 1},
	},
	LatinOffset: 2,
}

// marshalSFV serializes as defined in
// https://httpwg.org/specs/rfc9651.html#ser-string.
func ( DisplayString) ( *strings.Builder) error {
	if ,  := .WriteString(`%"`);  != nil {
		return 
	}

	for  := 0;  < len(); ++ {
		if [] == '%' || [] == '"' || unicode.Is(notVcharOrSp, rune([])) {
			.WriteRune('%')
			.WriteString(hex.EncodeToString([]byte{[]}))

			continue
		}

		.WriteByte([])
	}

	.WriteByte('"')

	return nil
}

// parseDisplayString parses as defined in
// https://httpwg.org/specs/rfc9651.html#parse-display.
func parseDisplayString( *scanner) (DisplayString, error) {
	if .eof() || len(.data[.off:]) < 2 || .data[.off:2] != `%"` {
		return "", &UnmarshalError{.off, ErrInvalidDisplayString}
	}
	.off += 2

	var  strings.Builder
	for !.eof() {
		 := .data[.off]
		.off++

		switch  {
		case '%':
			if len(.data[.off:]) < 2 {
				return "", &UnmarshalError{.off, ErrInvalidDisplayString}
			}
			 := unhex(.data[.off])
			if  == 0 {
				return "", &UnmarshalError{.off, ErrInvalidDisplayString}
			}

			 := unhex(.data[.off+1])
			if  == 0 {
				return "", &UnmarshalError{.off, ErrInvalidDisplayString}
			}

			.WriteByte(<<4 | )
			.off += 2
		case '"':
			 := .String()
			if !utf8.ValidString() {
				return "", ErrInvalidDisplayString
			}

			return DisplayString(), nil

		default:
			if unicode.Is(notVcharOrSp, rune()) {
				return "", &UnmarshalError{.off, ErrInvalidDisplayString}
			}

			.WriteByte()
		}
	}

	return "", &UnmarshalError{.off, ErrInvalidDisplayString}
}

func unhex( byte) byte {
	switch {
	case '0' <=  &&  <= '9':
		return  - '0'
	case 'a' <=  &&  <= 'f':
		return  - 'a' + 10
	default:
		return 0
	}
}