package httprange

import (
	
	
	
	

	
)

// contentRangeHeader represents a Content-Range header value.
// It consists of a unit and a range response (e.g. "bytes 0-99/100").
type contentRangeHeader struct {
	Unit string
	Resp string
}

func ( string) (contentRangeHeader, bool) {
	// Note: RFC 9110 has a regression in Content-Range grammar: it only
	// allows bytes-like range-resp. We use the definition from RFC 7233
	// that allows other units.
	//
	// https://datatracker.ietf.org/doc/html/rfc9110
	// https://datatracker.ietf.org/doc/html/rfc7233

	, ,  := strings.Cut(, " ")
	if ! ||  == "" {
		return contentRangeHeader{}, false
	}

	for ,  := range  {
		if httpguts.IsTokenRune() {
			continue
		}
		return contentRangeHeader{}, false
	}

	for ,  := range  {
		if  > 0 &&  < 0x80 {
			continue
		}
		return contentRangeHeader{}, false
	}

	return contentRangeHeader{
		Unit: ,
		Resp: ,
	}, true
}

func ( http.Header,  string) (string, error) {
	 := .Get(httpHeaderContentRange)
	,  := parseContentRange()
	if ! {
		return "", fmt.Errorf(
			"httprange: invalid Content-Range header value %q",
			,
		)
	}
	if !equalFoldASCII(.Unit, ) {
		return "", fmt.Errorf(
			"httprange: unexpected range unit %q (expected %q)",
			.Unit, ,
		)
	}
	return .Resp, nil
}

type unsatisfiedRangeResp struct {
	CompleteLength int64
}

func ( string) (unsatisfiedRangeResp, bool) {
	,  := strings.CutPrefix(, "*/")
	if ! || !isDigits() {
		return unsatisfiedRangeResp{}, false
	}
	,  := strconv.ParseInt(, 10, 64)
	if  != nil {
		return unsatisfiedRangeResp{}, false
	}
	return unsatisfiedRangeResp{
		CompleteLength: ,
	}, true
}

type bytesRangeResp struct {
	First, Last    int64
	CompleteLength int64 // zero if unknown
}

func ( string) (bytesRangeResp, bool) {
	, ,  := strings.Cut(, "/")
	if ! {
		return bytesRangeResp{}, false
	}

	 :=  != "*"
	if  && !isDigits() {
		return bytesRangeResp{}, false
	}

	, ,  := strings.Cut(, "-")
	if ! || !isDigits() || !isDigits() {
		return bytesRangeResp{}, false
	}

	,  := strconv.ParseInt(, 10, 64)
	if  != nil {
		return bytesRangeResp{}, false
	}
	,  := strconv.ParseInt(, 10, 64)
	if  != nil {
		return bytesRangeResp{}, false
	}

	if  >  {
		return bytesRangeResp{}, false
	}

	var  int64
	if  {
		,  = strconv.ParseInt(, 10, 64)
		if  != nil {
			return bytesRangeResp{}, false
		}
		if  >=  {
			return bytesRangeResp{}, false
		}
	}

	return bytesRangeResp{
		First:          ,
		Last:           ,
		CompleteLength: ,
	}, true
}

func ( string) bool {
	if  == "" {
		return false
	}
	for  := range len() {
		if !isDigitASCII([]) {
			return false
		}
	}
	return true
}

func ( byte) bool {
	return '0' <=  &&  <= '9'
}