d82b290251
Merge in DNS/adguard-home from 4095-port-3000 to master Updates #4095. Squashed commit of the following: commit 968cc806264898523d29c4ec20b3ce6a69abb09c Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Wed Jan 19 20:26:33 2022 +0300 home: fix typo commit 03c6798db6a4ca726a7b5a683e475a8a74f79fe1 Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Wed Jan 19 20:20:34 2022 +0300 all: more naming imps commit d3d417fcb24a1859f53a743b3533faa81b6bef19 Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Wed Jan 19 20:10:14 2022 +0300 aghalgo: rename into aghalg commit 6e106006d07a747ff4ddf1271532106c3a3e2b20 Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Wed Jan 19 20:05:43 2022 +0300 all: imp names, docs commit 12c8d9fde0d0cc5b953da30b042171ba7c53da5d Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Wed Jan 19 19:57:21 2022 +0300 all: fix log of changes commit 49c7a705b9b1ad8f2ef68fa807f9b6b8c447b421 Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Wed Jan 19 19:51:00 2022 +0300 home: fix duplicating port 3000
76 lines
1.8 KiB
Go
76 lines
1.8 KiB
Go
// Package aghalg contains common generic algorithms and data structures.
|
|
//
|
|
// TODO(a.garipov): Update to use type parameters in Go 1.18.
|
|
package aghalg
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
)
|
|
|
|
// comparable is an alias for interface{}. Values passed as arguments of this
|
|
// type alias must be comparable.
|
|
//
|
|
// TODO(a.garipov): Remove in Go 1.18.
|
|
type comparable = interface{}
|
|
|
|
// UniqChecker allows validating uniqueness of comparable items.
|
|
type UniqChecker map[comparable]int64
|
|
|
|
// Add adds a value to the validator. v must not be nil.
|
|
func (uc UniqChecker) Add(elems ...comparable) {
|
|
for _, e := range elems {
|
|
uc[e]++
|
|
}
|
|
}
|
|
|
|
// Merge returns a validator containing data from both v and other.
|
|
func (uc UniqChecker) Merge(other UniqChecker) (merged UniqChecker) {
|
|
merged = make(UniqChecker, len(uc)+len(other))
|
|
for elem, num := range uc {
|
|
merged[elem] += num
|
|
}
|
|
|
|
for elem, num := range other {
|
|
merged[elem] += num
|
|
}
|
|
|
|
return merged
|
|
}
|
|
|
|
// Validate returns an error enumerating all elements that aren't unique.
|
|
// isBefore is an optional sorting function to make the error message
|
|
// deterministic.
|
|
func (uc UniqChecker) Validate(isBefore func(a, b comparable) (less bool)) (err error) {
|
|
var dup []comparable
|
|
for elem, num := range uc {
|
|
if num > 1 {
|
|
dup = append(dup, elem)
|
|
}
|
|
}
|
|
|
|
if len(dup) == 0 {
|
|
return nil
|
|
}
|
|
|
|
if isBefore != nil {
|
|
sort.Slice(dup, func(i, j int) (less bool) {
|
|
return isBefore(dup[i], dup[j])
|
|
})
|
|
}
|
|
|
|
return fmt.Errorf("duplicated values: %v", dup)
|
|
}
|
|
|
|
// IntIsBefore is a helper sort function for UniqChecker.Validate.
|
|
// a and b must be of type int.
|
|
func IntIsBefore(a, b comparable) (less bool) {
|
|
return a.(int) < b.(int)
|
|
}
|
|
|
|
// StringIsBefore is a helper sort function for UniqChecker.Validate.
|
|
// a and b must be of type string.
|
|
func StringIsBefore(a, b comparable) (less bool) {
|
|
return a.(string) < b.(string)
|
|
}
|