func ParseUintHex(b []byte) (uint64, error) {
	const max = Uint64Max
	const lim = max / 0x10
	var val uint64

	if len(b) == 0 {
		return 0, errorInvalidUint64(b)
	}

	for _, d := range b {
		var x uint64

		switch {
		case d >= '0' && d <= '9':
			x = uint64(d - '0')

		case d >= 'A' && d <= 'F':
			x = uint64(d-'A') + 0xA

		case d >= 'a' && d <= 'f':
			x = uint64(d-'a') + 0xA

		default:
			return 0, errorInvalidUint64(b)
		}

		if val > lim {
			return 0, errorOverflowUint64(b)
		}

		if val *= 0x10; val > (max - x) {
			return 0, errorOverflowUint64(b)
		}

		val += x
	}

	return val, nil
}
func ParseUintHex(b []byte) (uint64, error) {
	const max = Uint64Max
	const lim = max / 0x10
	var val uint64

	if len(b) == 0 {
		return 0, errorInvalidUint64(b)
	}

	for _, d := range b {
		var x uint64

		switch {
		case d >= '0' && d <= '9':
			x = uint64(d - '0')

		case d >= 'A' && d <= 'F':
			x = uint64(d-'A') + 0xA

		case d >= 'a' && d <= 'f':
			x = uint64(d-'a') + 0xA

		default:
			return 0, errorInvalidUint64(b)
		}

		if val > lim {
			return 0, errorOverflowUint64(b)
		}

		if val *= 0x10; val > (max - x) {
			return 0, errorOverflowUint64(b)
		}

		val += x
	}

	return val, nil
}
// ParseUintHex parses a hexadecimanl representation of a uint64 from b.
//
// The function is equivalent to calling strconv.ParseUint(string(b), 16, 64) but
// it prevents Go from making a memory allocation for converting a byte slice to
// a string (escape analysis fails due to the error returned by strconv.ParseUint).
//
// Because it only works with base 16 the function is also significantly faster
// than strconv.ParseUint.