1package common
2
3// UnsafeUTF8DecimalCodePointsToInt converts a slice containing
4// a series of UTF-8 decimal code points into their integer rapresentation.
5//
6// It assumes input code points are in the range 48-57.
7// Returns a pointer since an empty slice is equal to nil and not to the zero value of the codomain (ie., `int`).
8func UnsafeUTF8DecimalCodePointsToInt(chars []uint8) int {
9	out := 0
10	ord := 1
11	for i := len(chars) - 1; i >= 0; i-- {
12		curchar := int(chars[i])
13		out += (curchar - '0') * ord
14		ord *= 10
15	}
16	return out
17}
18
19// RemoveBytes removes byte at given positions from data byte slice, starting from the given offset.
20func RemoveBytes(data []byte, positions []int, offset int) []byte {
21	// We need a copy here to not modify original data
22	cp := append([]byte(nil), data...)
23	for i, pos := range positions {
24		at := pos - i - offset
25		cp = append(cp[:at], cp[(at+1):]...)
26	}
27	return cp
28}
29
30// EscapeBytes adds a backslash to \, ], " characters.
31func EscapeBytes(value string) string {
32	res := ""
33	for i, c := range value {
34		// todo(leodido): generalize byte codes (the function should ideally accept a byte slice containing byte codes to escape)
35		if c == 92 || c == 93 || c == 34 {
36			res += `\`
37		}
38		res += string(value[i])
39	}
40
41	return res
42}
43
44// InBetween tells whether value is into [min, max] range.
45func InBetween(val, min, max int) bool {
46	return val >= min && val <= max
47}
48
49// ValidPriority checks whether the given value is in the priority range [0, 191].
50func ValidPriority(priority uint8) bool {
51	return InBetween(int(priority), 0, 191)
52}
53
54// ValidVersion checks whether the given value is in the version range [1, 999].
55func ValidVersion(version uint16) bool {
56	return InBetween(int(version), 1, 999)
57}
58