// Copyright 2024 The quic-go Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file of
// the quic-go repository.

package quicvarint

import (
	
	

	
)

// taken from the QUIC draft
const (
	// Min is the minimum value allowed for a QUIC varint.
	Min = 0

	// Max is the maximum allowed value for a QUIC varint (2^62-1).
	Max = maxVarInt8

	maxVarInt1 = 63
	maxVarInt2 = 16383
	maxVarInt4 = 1073741823
	maxVarInt8 = 4611686018427387903
)

// Read reads a number in the QUIC varint format from r.
func ( io.ByteReader) (uint64, error) {
	,  := .ReadByte()
	if  != nil {
		return 0, 
	}
	// the first two bits of the first byte encode the length
	 := 1 << (( & 0xc0) >> 6)
	 :=  & (0xff - 0xc0)
	if  == 1 {
		return uint64(), nil
	}
	,  := .ReadByte()
	if  != nil {
		return 0, 
	}
	if  == 2 {
		return uint64() + uint64()<<8, nil
	}
	,  := .ReadByte()
	if  != nil {
		return 0, 
	}
	,  := .ReadByte()
	if  != nil {
		return 0, 
	}
	if  == 4 {
		return uint64() + uint64()<<8 + uint64()<<16 + uint64()<<24, nil
	}
	,  := .ReadByte()
	if  != nil {
		return 0, 
	}
	,  := .ReadByte()
	if  != nil {
		return 0, 
	}
	,  := .ReadByte()
	if  != nil {
		return 0, 
	}
	,  := .ReadByte()
	if  != nil {
		return 0, 
	}
	return uint64() + uint64()<<8 + uint64()<<16 + uint64()<<24 + uint64()<<32 + uint64()<<40 + uint64()<<48 + uint64()<<56, nil
}

// Append appends i in the QUIC varint format.
func ( []byte,  uint64) []byte {
	if  <= maxVarInt1 {
		return append(, uint8())
	}
	if  <= maxVarInt2 {
		return append(, []byte{uint8(>>8) | 0x40, uint8()}...)
	}
	if  <= maxVarInt4 {
		return append(, []byte{uint8(>>24) | 0x80, uint8( >> 16), uint8( >> 8), uint8()}...)
	}
	if  <= maxVarInt8 {
		return append(, []byte{
			uint8(>>56) | 0xc0, uint8( >> 48), uint8( >> 40), uint8( >> 32),
			uint8( >> 24), uint8( >> 16), uint8( >> 8), uint8(),
		}...)
	}
	panic(fmt.Sprintf("%#x doesn't fit into 62 bits", ))
}

// AppendWithLen append i in the QUIC varint format with the desired length.
func ( []byte,  uint64,  protocol.ByteCount) []byte {
	if  != 1 &&  != 2 &&  != 4 &&  != 8 {
		panic("invalid varint length")
	}
	 := Len()
	if  ==  {
		return Append(, )
	}
	if  >  {
		panic(fmt.Sprintf("cannot encode %d in %d bytes", , ))
	}
	if  == 2 {
		 = append(, 0b01000000)
	} else if  == 4 {
		 = append(, 0b10000000)
	} else if  == 8 {
		 = append(, 0b11000000)
	}
	for  := protocol.ByteCount(1);  < -; ++ {
		 = append(, 0)
	}
	for  := protocol.ByteCount(0);  < ; ++ {
		 = append(, uint8(>>(8*(-1-))))
	}
	return 
}

// Len determines the number of bytes that will be needed to write the number i.
func ( uint64) protocol.ByteCount {
	if  <= maxVarInt1 {
		return 1
	}
	if  <= maxVarInt2 {
		return 2
	}
	if  <= maxVarInt4 {
		return 4
	}
	if  <= maxVarInt8 {
		return 8
	}
	// Don't use a fmt.Sprintf here to format the error message.
	// The function would then exceed the inlining budget.
	panic(struct {
		 string
		     uint64
	}{"value doesn't fit into 62 bits: ", })
}