Pull request: upd-go

Merge in DNS/adguard-home from upd-go to master

Squashed commit of the following:

commit 8edfb5cc3466c1e4ee2eacae5157bd93c135a284
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Aug 3 14:25:45 2022 +0300

    all: imp docs; fmt

commit 080b8a85c02afbdaa079c0da47cb7b6311d50fbe
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Aug 2 20:51:20 2022 +0300

    all: upd go, imp generic code
This commit is contained in:
Ainar Garipov
2022-08-03 14:36:18 +03:00
parent da32079516
commit 9ed8699c75
35 changed files with 302 additions and 315 deletions

View File

@@ -1,32 +1,31 @@
// Package aghalg contains common generic algorithms and data structures.
//
// TODO(a.garipov): Update to use type parameters in Go 1.18.
// TODO(a.garipov): Move parts of this into golibs.
package aghalg
import (
"fmt"
"sort"
"golang.org/x/exp/constraints"
"golang.org/x/exp/slices"
)
// 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
//
// TODO(a.garipov): The Ordered constraint is only really necessary in Validate.
// Consider ways of making this constraint comparable instead.
type UniqChecker[T constraints.Ordered] map[T]int64
// Add adds a value to the validator. v must not be nil.
func (uc UniqChecker) Add(elems ...comparable) {
func (uc UniqChecker[T]) Add(elems ...T) {
for _, e := range elems {
uc[e]++
}
}
// Merge returns a checker containing data from both uc and other.
func (uc UniqChecker) Merge(other UniqChecker) (merged UniqChecker) {
merged = make(UniqChecker, len(uc)+len(other))
func (uc UniqChecker[T]) Merge(other UniqChecker[T]) (merged UniqChecker[T]) {
merged = make(UniqChecker[T], len(uc)+len(other))
for elem, num := range uc {
merged[elem] += num
}
@@ -39,10 +38,8 @@ func (uc UniqChecker) Merge(other UniqChecker) (merged UniqChecker) {
}
// 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
func (uc UniqChecker[T]) Validate() (err error) {
var dup []T
for elem, num := range uc {
if num > 1 {
dup = append(dup, elem)
@@ -53,23 +50,7 @@ func (uc UniqChecker) Validate(isBefore func(a, b comparable) (less bool)) (err
return nil
}
if isBefore != nil {
sort.Slice(dup, func(i, j int) (less bool) {
return isBefore(dup[i], dup[j])
})
}
slices.Sort(dup)
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)
}