package yu_proto

import yu_math "gogs.qqck.cn/s/tools/math"

// MaxVarintLenN is the maximum length of a varint-encoded N-bit integer.
const (
	maxVarintLen16 = 3
	maxVarintLen32 = 5
	maxVarintLen64 = 10
)

func appendInt64(buf []byte, x int64) []byte {
	if x >= 0 {
		return appendUint64(buf, uint64(x)<<1)
	} else {
		return appendUint64(buf, ^uint64(x)<<1)
	}
}

func appendUint64(buf []byte, x uint64) []byte {
	for x >= 0x80 {
		buf = append(buf, byte(x)|0x80)
		x >>= 7
	}
	return append(buf, byte(x))
}

func appendFloat32(buf []byte, x float32) []byte {
	v := yu_math.Float32bits(x)
	buf = append(buf, byte(v))
	buf = append(buf, byte(v>>8))
	buf = append(buf, byte(v>>16))
	return append(buf, byte(v>>24))
}

func appendFloat64(buf []byte, x float64) []byte {
	v := yu_math.Float64bits(x)
	buf = append(buf, byte(v))
	buf = append(buf, byte(v>>8))
	buf = append(buf, byte(v>>16))
	buf = append(buf, byte(v>>24))
	buf = append(buf, byte(v>>32))
	buf = append(buf, byte(v>>40))
	buf = append(buf, byte(v>>48))
	return append(buf, byte(v>>56))
}

// Uvarint decodes a uint64 from buf and returns that value and the
// number of bytes read (> 0). If an error occurred, the value is 0
// and the number of bytes n is <= 0 meaning:
//
//	n == 0: buf too small
//	n  < 0: value larger than 64 bits (overflow)
//	        and -n is the number of bytes read
func getUint64(buf []byte) (uint64, int) {
	var x uint64
	var s uint
	for i, b := range buf {
		if i == maxVarintLen64 {
			// Catch byte reads past MaxVarintLen64.
			// See issue https://golang.org/issues/41185
			return 0, -(i + 1) // overflow
		}
		if b < 0x80 {
			if i == maxVarintLen64-1 && b > 1 {
				return 0, -(i + 1) // overflow
			}
			return x | uint64(b)<<s, i + 1
		}
		x |= uint64(b&0x7f) << s
		s += 7
	}
	return 0, 0
}
