// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build go1.24

package http3

import (
	"errors"
	"math/bits"
)

type qpackDecoder struct {
	// The decoder has no state for now,
	// but that'll change once we add dynamic table support.
	//
	// TODO: dynamic table support.
}

func (qd *qpackDecoder) decode(st *stream, f func(itype indexType, name, value string) error) error {
	// Encoded Field Section prefix.

	// We set SETTINGS_QPACK_MAX_TABLE_CAPACITY to 0,
	// so the Required Insert Count must be 0.
	_, requiredInsertCount, err := st.readPrefixedInt(8)
	if err != nil {
		return err
	}
	if requiredInsertCount != 0 {
		return errQPACKDecompressionFailed
	}

	// Delta Base. We don't use the dynamic table yet, so this may be ignored.
	_, _, err = st.readPrefixedInt(7)
	if err != nil {
		return err
	}

	sawNonPseudo := false
	for st.lim > 0 {
		firstByte, err := st.ReadByte()
		if err != nil {
			return err
		}
		var name, value string
		var itype indexType
		switch bits.LeadingZeros8(firstByte) {
		case 0:
			// Indexed Field Line
			itype, name, value, err = st.decodeIndexedFieldLine(firstByte)
		case 1:
			// Literal Field Line With Name Reference
			itype, name, value, err = st.decodeLiteralFieldLineWithNameReference(firstByte)
		case 2:
			// Literal Field Line with Literal Name
			itype, name, value, err = st.decodeLiteralFieldLineWithLiteralName(firstByte)
		case 3:
			// Indexed Field Line With Post-Base Index
			err = errors.New("dynamic table is not supported yet")
		case 4:
			// Indexed Field Line With Post-Base Name Reference
			err = errors.New("dynamic table is not supported yet")
		}
		if err != nil {
			return err
		}
		if len(name) == 0 {
			return errH3MessageError
		}
		if name[0] == ':' {
			if sawNonPseudo {
				return errH3MessageError
			}
		} else {
			sawNonPseudo = true
		}
		if err := f(itype, name, value); err != nil {
			return err
		}
	}
	return nil
}
