Update dependencies
This commit is contained in:
202
vendor/go4.org/mem/LICENSE
generated
vendored
Normal file
202
vendor/go4.org/mem/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
3
vendor/go4.org/mem/README.md
generated
vendored
Normal file
3
vendor/go4.org/mem/README.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# go4.org/mem
|
||||
|
||||
See https://godoc.org/go4.org/mem
|
||||
103
vendor/go4.org/mem/fields.go
generated
vendored
Normal file
103
vendor/go4.org/mem/fields.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
Copyright 2020 The Go4 AUTHORS
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package mem
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1}
|
||||
|
||||
// AppendFields is like strings.Fields, but is append-like and uses a mem.RO instead of a string.
|
||||
func AppendFields(dst []RO, m RO) []RO {
|
||||
s := m.m
|
||||
|
||||
// Copied from the Go standard library (BSD license).
|
||||
|
||||
// First count the fields.
|
||||
// This is an exact count if s is ASCII, otherwise it is an approximation.
|
||||
n := 0
|
||||
wasSpace := 1
|
||||
// setBits is used to track which bits are set in the bytes of s.
|
||||
setBits := uint8(0)
|
||||
for i := 0; i < len(s); i++ {
|
||||
r := s[i]
|
||||
setBits |= r
|
||||
isSpace := int(asciiSpace[r])
|
||||
n += wasSpace & ^isSpace
|
||||
wasSpace = isSpace
|
||||
}
|
||||
|
||||
if setBits >= utf8.RuneSelf {
|
||||
// Some runes in the input string are not ASCII.
|
||||
return AppendFieldsFunc(dst, m, unicode.IsSpace)
|
||||
}
|
||||
// ASCII fast path
|
||||
fieldStart := 0
|
||||
i := 0
|
||||
// Skip spaces in the front of the input.
|
||||
for i < len(s) && asciiSpace[s[i]] != 0 {
|
||||
i++
|
||||
}
|
||||
fieldStart = i
|
||||
for i < len(s) {
|
||||
if asciiSpace[s[i]] == 0 {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
dst = append(dst, RO{m: s[fieldStart:i]})
|
||||
i++
|
||||
// Skip spaces in between fields.
|
||||
for i < len(s) && asciiSpace[s[i]] != 0 {
|
||||
i++
|
||||
}
|
||||
fieldStart = i
|
||||
}
|
||||
if fieldStart < len(s) { // Last field might end at EOF.
|
||||
dst = append(dst, RO{m: s[fieldStart:]})
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendFieldsFunc is like strings.FieldsFunc, but is append-like and uses a mem.RO instead of a string.
|
||||
func AppendFieldsFunc(dst []RO, m RO, f func(rune) bool) []RO {
|
||||
s := string(m.m)
|
||||
|
||||
// Find the field start and end indices.
|
||||
wasField := false
|
||||
fromIndex := 0
|
||||
for i, rune := range s {
|
||||
if f(rune) {
|
||||
if wasField {
|
||||
dst = append(dst, RO{m: unsafeString(s[fromIndex:i])})
|
||||
wasField = false
|
||||
}
|
||||
} else {
|
||||
if !wasField {
|
||||
fromIndex = i
|
||||
wasField = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Last field might end at EOF.
|
||||
if wasField {
|
||||
dst = append(dst, RO{m: unsafeString(s[fromIndex:len(s)])})
|
||||
}
|
||||
return dst
|
||||
}
|
||||
132
vendor/go4.org/mem/fold.go
generated
vendored
Normal file
132
vendor/go4.org/mem/fold.go
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright 2020 The Go4 AUTHORS
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package mem // import "go4.org/mem"
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// equalFoldRune compares a and b runes whether they fold equally.
|
||||
//
|
||||
// The code comes from strings.EqualFold, but shortened to only one rune.
|
||||
func equalFoldRune(sr, tr rune) bool {
|
||||
if sr == tr {
|
||||
return true
|
||||
}
|
||||
// Make sr < tr to simplify what follows.
|
||||
if tr < sr {
|
||||
sr, tr = tr, sr
|
||||
}
|
||||
// Fast check for ASCII.
|
||||
if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' {
|
||||
// ASCII, and sr is upper case. tr must be lower case.
|
||||
if tr == sr+'a'-'A' {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// General case. SimpleFold(x) returns the next equivalent rune > x
|
||||
// or wraps around to smaller values.
|
||||
r := unicode.SimpleFold(sr)
|
||||
for r != sr && r < tr {
|
||||
r = unicode.SimpleFold(r)
|
||||
}
|
||||
if r == tr {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HasPrefixFold is like HasPrefix but uses Unicode case-folding,
|
||||
// matching case insensitively.
|
||||
func HasPrefixFold(s, prefix RO) bool {
|
||||
if strings.HasPrefix(s.str(), prefix.str()) {
|
||||
// Exact case fast path.
|
||||
return true
|
||||
}
|
||||
for _, pr := range prefix.str() {
|
||||
if s.Len() == 0 {
|
||||
return false
|
||||
}
|
||||
// step with s, too
|
||||
sr, size := utf8.DecodeRuneInString(s.str())
|
||||
if sr == utf8.RuneError {
|
||||
return false
|
||||
}
|
||||
s = s.SliceFrom(size)
|
||||
if !equalFoldRune(sr, pr) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// HasSuffixFold is like HasSuffix but uses Unicode case-folding,
|
||||
// matching case insensitively.
|
||||
func HasSuffixFold(s, suffix RO) bool {
|
||||
if suffix.Len() == 0 {
|
||||
return true
|
||||
}
|
||||
if strings.HasSuffix(s.str(), suffix.str()) {
|
||||
// Exact case fast path.
|
||||
return true
|
||||
}
|
||||
// count the runes and bytes in s, but only until rune count of suffix
|
||||
bo, so := s.Len(), suffix.Len()
|
||||
for bo > 0 && so > 0 {
|
||||
r, size := utf8.DecodeLastRuneInString(s.str()[:bo])
|
||||
if r == utf8.RuneError {
|
||||
return false
|
||||
}
|
||||
bo -= size
|
||||
|
||||
sr, size := utf8.DecodeLastRuneInString(suffix.str()[:so])
|
||||
if sr == utf8.RuneError {
|
||||
return false
|
||||
}
|
||||
so -= size
|
||||
|
||||
if !equalFoldRune(r, sr) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return so == 0
|
||||
}
|
||||
|
||||
// ContainsFold is like Contains but uses Unicode case-folding for a case insensitive substring search.
|
||||
func ContainsFold(s, substr RO) bool {
|
||||
if substr.Len() == 0 || strings.Contains(s.str(), substr.str()) {
|
||||
// Easy cases.
|
||||
return true
|
||||
}
|
||||
if s.Len() == 0 {
|
||||
return false
|
||||
}
|
||||
firstRune := rune(substr.At(0)) // Len != 0 checked above
|
||||
if firstRune >= utf8.RuneSelf {
|
||||
firstRune, _ = utf8.DecodeRuneInString(substr.str())
|
||||
}
|
||||
for i, rune := range s.str() {
|
||||
if equalFoldRune(rune, firstRune) && HasPrefixFold(s.SliceFrom(i), substr) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
313
vendor/go4.org/mem/mem.go
generated
vendored
Normal file
313
vendor/go4.org/mem/mem.go
generated
vendored
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
Copyright 2020 The Go4 AUTHORS
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package mem provides the mem.RO type that allows you to cheaply pass &
|
||||
// access either a read-only []byte or a string.
|
||||
package mem // import "go4.org/mem"
|
||||
|
||||
import (
|
||||
"hash/maphash"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// RO is a read-only view of some bytes of memory. It may be be backed
|
||||
// by a string or []byte. Notably, unlike a string, the memory is not
|
||||
// guaranteed to be immutable. While the length is fixed, the
|
||||
// underlying bytes might change if interleaved with code that's
|
||||
// modifying the underlying memory.
|
||||
//
|
||||
// RO is a value type that's the same size of a Go string. Its various
|
||||
// methods should inline & compile to the equivalent operations
|
||||
// working on a string or []byte directly.
|
||||
//
|
||||
// Unlike a Go string, RO is not 'comparable' (it can't be a map key
|
||||
// or support ==). Use its Equal method to compare. This is done so an
|
||||
// RO backed by a later-mutating []byte doesn't break invariants in
|
||||
// Go's map implementation.
|
||||
type RO struct {
|
||||
_ [0]func() // not comparable; don't want to be a map key or support ==
|
||||
m unsafeString
|
||||
}
|
||||
|
||||
// str returns the unsafeString as a string. Only for use with standard
|
||||
// library funcs known to not let the string escape, as it doesn't
|
||||
// obey the language/runtime's expectations of a real string (it can
|
||||
// change underfoot).
|
||||
func (r RO) str() string { return string(r.m) }
|
||||
|
||||
// Len returns len(r).
|
||||
func (r RO) Len() int { return len(r.m) }
|
||||
|
||||
// At returns r[i].
|
||||
func (r RO) At(i int) byte { return r.m[i] }
|
||||
|
||||
// Slice returns r[from:to].
|
||||
func (r RO) Slice(from, to int) RO { return RO{m: r.m[from:to]} }
|
||||
|
||||
// SliceFrom returns r[from:].
|
||||
func (r RO) SliceFrom(from int) RO { return RO{m: r.m[from:]} }
|
||||
|
||||
// SliceTo returns r[:to].
|
||||
func (r RO) SliceTo(to int) RO { return RO{m: r.m[:to]} }
|
||||
|
||||
// Copy copies up to len(dest) bytes into dest from r and returns the
|
||||
// number of bytes copied, the min(r.Len(), len(dest)).
|
||||
func (r RO) Copy(dest []byte) int { return copy(dest, r.m) }
|
||||
|
||||
// Equal reports whether r and r2 are the same length and contain the
|
||||
// same bytes.
|
||||
func (r RO) Equal(r2 RO) bool { return r.m == r2.m }
|
||||
|
||||
// EqualString reports whether r and s are the same length and contain
|
||||
// the same bytes.
|
||||
func (r RO) EqualString(s string) bool { return r.str() == s }
|
||||
|
||||
// EqualBytes reports whether r and b are the same length and contain
|
||||
// the same bytes.
|
||||
func (r RO) EqualBytes(b []byte) bool { return r.str() == string(b) }
|
||||
|
||||
// Less reports whether r < r2.
|
||||
func (r RO) Less(r2 RO) bool { return r.str() < r2.str() }
|
||||
|
||||
var builderPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(strings.Builder)
|
||||
},
|
||||
}
|
||||
|
||||
// StringCopy returns m's contents in a newly allocated string.
|
||||
func (r RO) StringCopy() string {
|
||||
buf := builderPool.Get().(*strings.Builder)
|
||||
defer builderPool.Put(buf)
|
||||
defer buf.Reset()
|
||||
buf.WriteString(r.str())
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
var seed = maphash.MakeSeed()
|
||||
|
||||
// MapHash returns a hash of r's contents using runtime/maphash.
|
||||
// The hash is stable for the lifetime of a process.
|
||||
func (r RO) MapHash() uint64 {
|
||||
var hash maphash.Hash
|
||||
hash.SetSeed(seed)
|
||||
hash.WriteString(r.str())
|
||||
return hash.Sum64()
|
||||
}
|
||||
|
||||
// ParseInt returns a signed integer from m, using strconv.ParseInt.
|
||||
func ParseInt(m RO, base, bitSize int) (int64, error) {
|
||||
return strconv.ParseInt(m.str(), base, bitSize)
|
||||
}
|
||||
|
||||
// ParseUint returns a unsigned integer from m, using strconv.ParseUint.
|
||||
func ParseUint(m RO, base, bitSize int) (uint64, error) {
|
||||
return strconv.ParseUint(m.str(), base, bitSize)
|
||||
}
|
||||
|
||||
// ParseFloat returns a float from, using strconv.ParseFloat.
|
||||
func ParseFloat(m RO, bitSize int) (float64, error) {
|
||||
return strconv.ParseFloat(m.str(), bitSize)
|
||||
}
|
||||
|
||||
// Append appends m to dest, and returns the possibly-reallocated
|
||||
// dest.
|
||||
func Append(dest []byte, m RO) []byte { return append(dest, m.m...) }
|
||||
|
||||
// Contains reports whether substr is within m.
|
||||
func Contains(m, substr RO) bool { return strings.Contains(m.str(), substr.str()) }
|
||||
|
||||
// EqualFold reports whether s and t, interpreted as UTF-8 strings,
|
||||
// are equal under Unicode case-folding, which is a more general form
|
||||
// of case-insensitivity.
|
||||
func EqualFold(m, m2 RO) bool { return strings.EqualFold(m.str(), m2.str()) }
|
||||
|
||||
// HasPrefix reports whether m starts with prefix.
|
||||
func HasPrefix(m, prefix RO) bool { return strings.HasPrefix(m.str(), prefix.str()) }
|
||||
|
||||
// HasSuffix reports whether m ends with suffix.
|
||||
func HasSuffix(m, suffix RO) bool { return strings.HasSuffix(m.str(), suffix.str()) }
|
||||
|
||||
// Index returns the index of the first instance of substr in m, or -1
|
||||
// if substr is not present in m.
|
||||
func Index(m, substr RO) int { return strings.Index(m.str(), substr.str()) }
|
||||
|
||||
// IndexByte returns the index of the first instance of c in m, or -1
|
||||
// if c is not present in m.
|
||||
func IndexByte(m RO, c byte) int { return strings.IndexByte(m.str(), c) }
|
||||
|
||||
// LastIndexByte returns the index into m of the last Unicode code
|
||||
// point satisfying f(c), or -1 if none do.
|
||||
func LastIndexByte(m RO, c byte) int { return strings.LastIndexByte(m.str(), c) }
|
||||
|
||||
// LastIndex returns the index of the last instance of substr in m, or
|
||||
// -1 if substr is not present in m.
|
||||
func LastIndex(m, substr RO) int { return strings.LastIndex(m.str(), substr.str()) }
|
||||
|
||||
// TrimSpace returns a slice of the string s, with all leading and
|
||||
// trailing white space removed, as defined by Unicode.
|
||||
func TrimSpace(m RO) RO { return S(strings.TrimSpace(m.str())) }
|
||||
|
||||
// TrimSuffix returns m without the provided trailing suffix.
|
||||
// If m doesn't end with suffix, m is returned unchanged.
|
||||
func TrimSuffix(m, suffix RO) RO {
|
||||
return S(strings.TrimSuffix(m.str(), suffix.str()))
|
||||
}
|
||||
|
||||
// TrimPrefix returns m without the provided leading prefix.
|
||||
// If m doesn't start with prefix, m is returned unchanged.
|
||||
func TrimPrefix(m, prefix RO) RO {
|
||||
return S(strings.TrimPrefix(m.str(), prefix.str()))
|
||||
}
|
||||
|
||||
// TrimRightCutset returns a slice of m with all trailing Unicode code
|
||||
// points contained in cutset removed.
|
||||
//
|
||||
// To remove a suffix, use TrimSuffix instead.
|
||||
func TrimRightCutset(m, cutset RO) RO {
|
||||
return S(strings.TrimRight(m.str(), cutset.str()))
|
||||
}
|
||||
|
||||
// TrimLeftCutset returns a slice of m with all leading Unicode code
|
||||
// points contained in cutset removed.
|
||||
//
|
||||
// To remove a prefix, use TrimPrefix instead.
|
||||
func TrimLeftCutset(m, cutset RO) RO {
|
||||
return S(strings.TrimLeft(m.str(), cutset.str()))
|
||||
}
|
||||
|
||||
// TrimCutset returns a slice of the string s with all leading and
|
||||
// trailing Unicode code points contained in cutset removed.
|
||||
func TrimCutset(m, cutset RO) RO {
|
||||
return S(strings.Trim(m.str(), cutset.str()))
|
||||
}
|
||||
|
||||
// TrimFunc returns a slice of m with all leading and trailing Unicode
|
||||
// code points c satisfying f(c) removed.
|
||||
func TrimFunc(m RO, f func(rune) bool) RO {
|
||||
return S(strings.TrimFunc(m.str(), f))
|
||||
}
|
||||
|
||||
// TrimRightFunc returns a slice of m with all trailing Unicode
|
||||
// code points c satisfying f(c) removed.
|
||||
func TrimRightFunc(m RO, f func(rune) bool) RO {
|
||||
return S(strings.TrimRightFunc(m.str(), f))
|
||||
}
|
||||
|
||||
// TrimLeftFunc returns a slice of m with all leading Unicode
|
||||
// code points c satisfying f(c) removed.
|
||||
func TrimLeftFunc(m RO, f func(rune) bool) RO {
|
||||
return S(strings.TrimLeftFunc(m.str(), f))
|
||||
}
|
||||
|
||||
// Documentation for UTF-8 related functions copied from Go's unicode/utf8 package. (BSD license)
|
||||
|
||||
// DecodeRune unpacks the first UTF-8 encoding in m and returns the rune and
|
||||
// its width in bytes. If m is empty it returns (utf8.RuneError, 0). Otherwise, if
|
||||
// the encoding is invalid, it returns (utf8.RuneError, 1). Both are impossible
|
||||
// results for correct, non-empty UTF-8.
|
||||
//
|
||||
// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
|
||||
// out of range, or is not the shortest possible UTF-8 encoding for the
|
||||
// value. No other validation is performed.
|
||||
func DecodeRune(m RO) (r rune, size int) {
|
||||
return utf8.DecodeRuneInString(m.str())
|
||||
}
|
||||
|
||||
// DecodeLastRune unpacks the last UTF-8 encoding in m and returns the rune and
|
||||
// its width in bytes. If m is empty it returns (utf8.RuneError, 0). Otherwise, if
|
||||
// the encoding is invalid, it returns (utf8.RuneError, 1). Both are impossible
|
||||
// results for correct, non-empty UTF-8.
|
||||
//
|
||||
// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
|
||||
// out of range, or is not the shortest possible UTF-8 encoding for the
|
||||
// value. No other validation is performed.
|
||||
func DecodeLastRune(m RO) (r rune, size int) {
|
||||
return utf8.DecodeLastRuneInString(m.str())
|
||||
}
|
||||
|
||||
// FullRune reports whether the bytes in m begin with a full UTF-8 encoding of a rune.
|
||||
// An invalid encoding is considered a full Rune since it will convert as a width-1 error rune.
|
||||
func FullRune(m RO) bool {
|
||||
return utf8.FullRuneInString(m.str())
|
||||
}
|
||||
|
||||
// RuneCount returns the number of UTF-8 encoded runes in m. Erroneous and short
|
||||
// encodings are treated as single runes of width 1 byte.
|
||||
func RuneCount(m RO) int {
|
||||
return utf8.RuneCountInString(m.str())
|
||||
}
|
||||
|
||||
// ValidUTF8 reports whether m consists entirely of valid UTF-8 encoded runes.
|
||||
func ValidUTF8(m RO) bool {
|
||||
return utf8.ValidString(m.str())
|
||||
}
|
||||
|
||||
// NewReader returns a new Reader that reads from m.
|
||||
func NewReader(m RO) *Reader {
|
||||
return &Reader{sr: strings.NewReader(m.str())}
|
||||
}
|
||||
|
||||
// Reader is like a bytes.Reader or strings.Reader.
|
||||
type Reader struct {
|
||||
sr *strings.Reader
|
||||
}
|
||||
|
||||
func (r *Reader) Len() int { return r.sr.Len() }
|
||||
func (r *Reader) Size() int64 { return r.sr.Size() }
|
||||
func (r *Reader) Read(b []byte) (int, error) { return r.sr.Read(b) }
|
||||
func (r *Reader) ReadAt(b []byte, off int64) (int, error) { return r.sr.ReadAt(b, off) }
|
||||
func (r *Reader) ReadByte() (byte, error) { return r.sr.ReadByte() }
|
||||
func (r *Reader) ReadRune() (ch rune, size int, err error) { return r.sr.ReadRune() }
|
||||
func (r *Reader) Seek(offset int64, whence int) (int64, error) { return r.sr.Seek(offset, whence) }
|
||||
|
||||
// TODO: add Reader.WriteTo, but don't use strings.Reader.WriteTo because it uses io.WriteString, leaking our unsafe string
|
||||
|
||||
// unsafeString is a string that's not really a Go string.
|
||||
// It might be pointing into a []byte. Don't let it escape to callers.
|
||||
// We contain the unsafety to this package.
|
||||
type unsafeString string
|
||||
|
||||
// stringHeader is a safer version of reflect.StringHeader.
|
||||
// See https://github.com/golang/go/issues/40701.
|
||||
type stringHeader struct {
|
||||
P *byte
|
||||
Len int
|
||||
}
|
||||
|
||||
// S returns a read-only view of the string s.
|
||||
//
|
||||
// The compiler should compile this call to nothing. Think of it as a
|
||||
// free type conversion. The returned RO view is the same size as a
|
||||
// string.
|
||||
func S(s string) RO { return RO{m: unsafeString(s)} }
|
||||
|
||||
// B returns a read-only view of the byte slice b.
|
||||
//
|
||||
// The compiler should compile this call to nothing. Think of it as a
|
||||
// free type conversion. The returned value is actually smaller than a
|
||||
// []byte though (16 bytes instead of 24 bytes on 64-bit
|
||||
// architectures).
|
||||
func B(b []byte) RO {
|
||||
if len(b) == 0 {
|
||||
return RO{m: ""}
|
||||
}
|
||||
return RO{m: *(*unsafeString)(unsafe.Pointer(&stringHeader{&b[0], len(b)}))}
|
||||
}
|
||||
3
vendor/go4.org/netipx/.gitignore
generated
vendored
Normal file
3
vendor/go4.org/netipx/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
crashers
|
||||
suppressions
|
||||
netaddr-fuzz.zip
|
||||
3
vendor/go4.org/netipx/.gitmodules
generated
vendored
Normal file
3
vendor/go4.org/netipx/.gitmodules
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "corpus"]
|
||||
path = corpus
|
||||
url = https://github.com/inetaf/netaddr-corpus.git
|
||||
4
vendor/go4.org/netipx/AUTHORS
generated
vendored
Normal file
4
vendor/go4.org/netipx/AUTHORS
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
Alex Willmer <alex@moreati.org.uk>
|
||||
Matt Layher <mdlayher@gmail.com>
|
||||
Tailscale Inc.
|
||||
Tobias Klauser <tklauser@distanz.ch>
|
||||
27
vendor/go4.org/netipx/LICENSE
generated
vendored
Normal file
27
vendor/go4.org/netipx/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2020 The Inet.af AUTHORS. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Tailscale Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
26
vendor/go4.org/netipx/README.md
generated
vendored
Normal file
26
vendor/go4.org/netipx/README.md
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
# netipx [](https://github.com/go4org/netipx/actions) [](https://pkg.go.dev/go4.org/netipx)
|
||||
|
||||
## What
|
||||
|
||||
This is a package containing the bits of the old `inet.af/netaddr` package that didn't make it
|
||||
into Go 1.18's `net/netip` standard library package.
|
||||
|
||||
As background, see:
|
||||
|
||||
* https://github.com/inetaf/netaddr/ (now deprecated)
|
||||
* https://tailscale.com/blog/netaddr-new-ip-type-for-go/ - blog post about why the package came to be originally
|
||||
* https://go.dev/doc/go1.18#netip - Go 1.18 release notes
|
||||
|
||||
This package requires Go 1.18+ to use and complements the `net/netip`.
|
||||
|
||||
## FAQ
|
||||
|
||||
**Why's it no longer under `inet.af`?** Since that joke started, that
|
||||
TLD is now under control of the Taliban. (Yes, we should've known
|
||||
better. We'd even previously scolded people for relying on
|
||||
questionable ccTLDs. Whoops.)
|
||||
|
||||
**Will this stuff make it into the standard library?** [Maybe](https://github.com/golang/go/issues/53236).
|
||||
We'll see.
|
||||
|
||||
|
||||
498
vendor/go4.org/netipx/ipset.go
generated
vendored
Normal file
498
vendor/go4.org/netipx/ipset.go
generated
vendored
Normal file
@@ -0,0 +1,498 @@
|
||||
// Copyright 2020 The Inet.Af AUTHORS. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package netipx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IPSetBuilder builds an immutable IPSet.
|
||||
//
|
||||
// The zero value is a valid value representing a set of no IPs.
|
||||
//
|
||||
// The Add and Remove methods add or remove IPs to/from the set.
|
||||
// Removals only affect the current membership of the set, so in
|
||||
// general Adds should be called first. Input ranges may overlap in
|
||||
// any way.
|
||||
//
|
||||
// Most IPSetBuilder methods do not return errors.
|
||||
// Instead, errors are accumulated and reported by IPSetBuilder.IPSet.
|
||||
type IPSetBuilder struct {
|
||||
// in are the ranges in the set.
|
||||
in []IPRange
|
||||
|
||||
// out are the ranges to be removed from 'in'.
|
||||
out []IPRange
|
||||
|
||||
// errs are errors accumulated during construction.
|
||||
errs multiErr
|
||||
}
|
||||
|
||||
// normalize normalizes s: s.in becomes the minimal sorted list of
|
||||
// ranges required to describe s, and s.out becomes empty.
|
||||
func (s *IPSetBuilder) normalize() {
|
||||
const debug = false
|
||||
if debug {
|
||||
debugf("ranges start in=%v out=%v", s.in, s.out)
|
||||
}
|
||||
in, ok := mergeIPRanges(s.in)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
out, ok := mergeIPRanges(s.out)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if debug {
|
||||
debugf("ranges sort in=%v out=%v", in, out)
|
||||
}
|
||||
|
||||
// in and out are sorted in ascending range order, and have no
|
||||
// overlaps within each other. We can run a merge of the two lists
|
||||
// in one pass.
|
||||
|
||||
min := make([]IPRange, 0, len(in))
|
||||
for len(in) > 0 && len(out) > 0 {
|
||||
rin, rout := in[0], out[0]
|
||||
if debug {
|
||||
debugf("step in=%v out=%v", rin, rout)
|
||||
}
|
||||
|
||||
switch {
|
||||
case !rout.IsValid() || !rin.IsValid():
|
||||
// mergeIPRanges should have prevented invalid ranges from
|
||||
// sneaking in.
|
||||
panic("invalid IPRanges during Ranges merge")
|
||||
case rout.entirelyBefore(rin):
|
||||
// "out" is entirely before "in".
|
||||
//
|
||||
// out in
|
||||
// f-------t f-------t
|
||||
out = out[1:]
|
||||
if debug {
|
||||
debugf("out before in; drop out")
|
||||
}
|
||||
case rin.entirelyBefore(rout):
|
||||
// "in" is entirely before "out".
|
||||
//
|
||||
// in out
|
||||
// f------t f-------t
|
||||
min = append(min, rin)
|
||||
in = in[1:]
|
||||
if debug {
|
||||
debugf("in before out; append in")
|
||||
debugf("min=%v", min)
|
||||
}
|
||||
case rin.coveredBy(rout):
|
||||
// "out" entirely covers "in".
|
||||
//
|
||||
// out
|
||||
// f-------------t
|
||||
// f------t
|
||||
// in
|
||||
in = in[1:]
|
||||
if debug {
|
||||
debugf("in inside out; drop in")
|
||||
}
|
||||
case rout.inMiddleOf(rin):
|
||||
// "in" entirely covers "out".
|
||||
//
|
||||
// in
|
||||
// f-------------t
|
||||
// f------t
|
||||
// out
|
||||
min = append(min, IPRange{from: rin.from, to: AddrPrior(rout.from)})
|
||||
// Adjust in[0], not ir, because we want to consider the
|
||||
// mutated range on the next iteration.
|
||||
in[0].from = rout.to.Next()
|
||||
out = out[1:]
|
||||
if debug {
|
||||
debugf("out inside in; split in, append first in, drop out, adjust second in")
|
||||
debugf("min=%v", min)
|
||||
}
|
||||
case rout.overlapsStartOf(rin):
|
||||
// "out" overlaps start of "in".
|
||||
//
|
||||
// out
|
||||
// f------t
|
||||
// f------t
|
||||
// in
|
||||
in[0].from = rout.to.Next()
|
||||
// Can't move ir onto min yet, another later out might
|
||||
// trim it further. Just discard or and continue.
|
||||
out = out[1:]
|
||||
if debug {
|
||||
debugf("out cuts start of in; adjust in, drop out")
|
||||
}
|
||||
case rout.overlapsEndOf(rin):
|
||||
// "out" overlaps end of "in".
|
||||
//
|
||||
// out
|
||||
// f------t
|
||||
// f------t
|
||||
// in
|
||||
min = append(min, IPRange{from: rin.from, to: AddrPrior(rout.from)})
|
||||
in = in[1:]
|
||||
if debug {
|
||||
debugf("merge out cuts end of in; append shortened in")
|
||||
debugf("min=%v", min)
|
||||
}
|
||||
default:
|
||||
// The above should account for all combinations of in and
|
||||
// out overlapping, but insert a panic to be sure.
|
||||
panic("unexpected additional overlap scenario")
|
||||
}
|
||||
}
|
||||
if len(in) > 0 {
|
||||
// Ran out of removals before the end of in.
|
||||
min = append(min, in...)
|
||||
if debug {
|
||||
debugf("min=%v", min)
|
||||
}
|
||||
}
|
||||
|
||||
s.in = min
|
||||
s.out = nil
|
||||
}
|
||||
|
||||
// Clone returns a copy of s that shares no memory with s.
|
||||
func (s *IPSetBuilder) Clone() *IPSetBuilder {
|
||||
return &IPSetBuilder{
|
||||
in: append([]IPRange(nil), s.in...),
|
||||
out: append([]IPRange(nil), s.out...),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *IPSetBuilder) addError(msg string, args ...interface{}) {
|
||||
se := new(stacktraceErr)
|
||||
// Skip three frames: runtime.Callers, addError, and the IPSetBuilder
|
||||
// method that called addError (such as IPSetBuilder.Add).
|
||||
// The resulting stack trace ends at the line in the user's
|
||||
// code where they called into netaddr.
|
||||
n := runtime.Callers(3, se.pcs[:])
|
||||
se.at = se.pcs[:n]
|
||||
se.err = fmt.Errorf(msg, args...)
|
||||
s.errs = append(s.errs, se)
|
||||
}
|
||||
|
||||
// Add adds ip to s.
|
||||
func (s *IPSetBuilder) Add(ip netip.Addr) {
|
||||
if !ip.IsValid() {
|
||||
s.addError("Add(IP{})")
|
||||
return
|
||||
}
|
||||
s.AddRange(IPRangeFrom(ip, ip))
|
||||
}
|
||||
|
||||
// AddPrefix adds all IPs in p to s.
|
||||
func (s *IPSetBuilder) AddPrefix(p netip.Prefix) {
|
||||
if r := RangeOfPrefix(p); r.IsValid() {
|
||||
s.AddRange(r)
|
||||
} else {
|
||||
s.addError("AddPrefix(%v/%v)", p.Addr(), p.Bits())
|
||||
}
|
||||
}
|
||||
|
||||
// AddRange adds r to s.
|
||||
// If r is not Valid, AddRange does nothing.
|
||||
func (s *IPSetBuilder) AddRange(r IPRange) {
|
||||
if !r.IsValid() {
|
||||
s.addError("AddRange(%v-%v)", r.From(), r.To())
|
||||
return
|
||||
}
|
||||
// If there are any removals (s.out), then we need to compact the set
|
||||
// first to get the order right.
|
||||
if len(s.out) > 0 {
|
||||
s.normalize()
|
||||
}
|
||||
s.in = append(s.in, r)
|
||||
}
|
||||
|
||||
// AddSet adds all IPs in b to s.
|
||||
func (s *IPSetBuilder) AddSet(b *IPSet) {
|
||||
if b == nil {
|
||||
return
|
||||
}
|
||||
for _, r := range b.rr {
|
||||
s.AddRange(r)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove removes ip from s.
|
||||
func (s *IPSetBuilder) Remove(ip netip.Addr) {
|
||||
if !ip.IsValid() {
|
||||
s.addError("Remove(IP{})")
|
||||
} else {
|
||||
s.RemoveRange(IPRangeFrom(ip, ip))
|
||||
}
|
||||
}
|
||||
|
||||
// RemovePrefix removes all IPs in p from s.
|
||||
func (s *IPSetBuilder) RemovePrefix(p netip.Prefix) {
|
||||
if r := RangeOfPrefix(p); r.IsValid() {
|
||||
s.RemoveRange(r)
|
||||
} else {
|
||||
s.addError("RemovePrefix(%v/%v)", p.Addr(), p.Bits())
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveRange removes all IPs in r from s.
|
||||
func (s *IPSetBuilder) RemoveRange(r IPRange) {
|
||||
if r.IsValid() {
|
||||
s.out = append(s.out, r)
|
||||
} else {
|
||||
s.addError("RemoveRange(%v-%v)", r.From(), r.To())
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveSet removes all IPs in o from s.
|
||||
func (s *IPSetBuilder) RemoveSet(b *IPSet) {
|
||||
if b == nil {
|
||||
return
|
||||
}
|
||||
for _, r := range b.rr {
|
||||
s.RemoveRange(r)
|
||||
}
|
||||
}
|
||||
|
||||
// removeBuilder removes all IPs in b from s.
|
||||
func (s *IPSetBuilder) removeBuilder(b *IPSetBuilder) {
|
||||
b.normalize()
|
||||
for _, r := range b.in {
|
||||
s.RemoveRange(r)
|
||||
}
|
||||
}
|
||||
|
||||
// Complement updates s to contain the complement of its current
|
||||
// contents.
|
||||
func (s *IPSetBuilder) Complement() {
|
||||
s.normalize()
|
||||
s.out = s.in
|
||||
s.in = []IPRange{
|
||||
RangeOfPrefix(netip.PrefixFrom(netip.AddrFrom4([4]byte{}), 0)),
|
||||
RangeOfPrefix(netip.PrefixFrom(netip.IPv6Unspecified(), 0)),
|
||||
}
|
||||
}
|
||||
|
||||
// Intersect updates s to the set intersection of s and b.
|
||||
func (s *IPSetBuilder) Intersect(b *IPSet) {
|
||||
var o IPSetBuilder
|
||||
o.Complement()
|
||||
o.RemoveSet(b)
|
||||
s.removeBuilder(&o)
|
||||
}
|
||||
|
||||
func discardf(format string, args ...interface{}) {}
|
||||
|
||||
// debugf is reassigned by tests.
|
||||
var debugf = discardf
|
||||
|
||||
// IPSet returns an immutable IPSet representing the current state of s.
|
||||
//
|
||||
// Most IPSetBuilder methods do not return errors.
|
||||
// Rather, the builder ignores any invalid inputs (such as an invalid IPPrefix),
|
||||
// and accumulates a list of any such errors that it encountered.
|
||||
//
|
||||
// IPSet also reports any such accumulated errors.
|
||||
// Even if the returned error is non-nil, the returned IPSet is usable
|
||||
// and contains all modifications made with valid inputs.
|
||||
//
|
||||
// The builder remains usable after calling IPSet.
|
||||
// Calling IPSet clears any accumulated errors.
|
||||
func (s *IPSetBuilder) IPSet() (*IPSet, error) {
|
||||
s.normalize()
|
||||
ret := &IPSet{
|
||||
rr: append([]IPRange{}, s.in...),
|
||||
}
|
||||
if len(s.errs) == 0 {
|
||||
return ret, nil
|
||||
} else {
|
||||
errs := s.errs
|
||||
s.errs = nil
|
||||
return ret, errs
|
||||
}
|
||||
}
|
||||
|
||||
// IPSet represents a set of IP addresses.
|
||||
//
|
||||
// IPSet is safe for concurrent use.
|
||||
// The zero value is a valid value representing a set of no IPs.
|
||||
// Use IPSetBuilder to construct IPSets.
|
||||
type IPSet struct {
|
||||
// rr is the set of IPs that belong to this IPSet. The IPRanges
|
||||
// are normalized according to IPSetBuilder.normalize, meaning
|
||||
// they are a sorted, minimal representation (no overlapping
|
||||
// ranges, no contiguous ranges). The implementation of various
|
||||
// methods rely on this property.
|
||||
rr []IPRange
|
||||
}
|
||||
|
||||
// Ranges returns the minimum and sorted set of IP
|
||||
// ranges that covers s.
|
||||
func (s *IPSet) Ranges() []IPRange {
|
||||
return append([]IPRange{}, s.rr...)
|
||||
}
|
||||
|
||||
// Prefixes returns the minimum and sorted set of IP prefixes
|
||||
// that covers s.
|
||||
func (s *IPSet) Prefixes() []netip.Prefix {
|
||||
out := make([]netip.Prefix, 0, len(s.rr))
|
||||
for _, r := range s.rr {
|
||||
out = append(out, r.Prefixes()...)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Equal reports whether s and o represent the same set of IP
|
||||
// addresses.
|
||||
func (s *IPSet) Equal(o *IPSet) bool {
|
||||
if len(s.rr) != len(o.rr) {
|
||||
return false
|
||||
}
|
||||
for i := range s.rr {
|
||||
if s.rr[i] != o.rr[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Contains reports whether ip is in s.
|
||||
// If ip has an IPv6 zone, Contains returns false,
|
||||
// because IPSets do not track zones.
|
||||
func (s *IPSet) Contains(ip netip.Addr) bool {
|
||||
if ip.Zone() != "" {
|
||||
return false
|
||||
}
|
||||
// TODO: data structure permitting more efficient lookups:
|
||||
// https://github.com/inetaf/netaddr/issues/139
|
||||
i := sort.Search(len(s.rr), func(i int) bool {
|
||||
return ip.Less(s.rr[i].from)
|
||||
})
|
||||
if i == 0 {
|
||||
return false
|
||||
}
|
||||
i--
|
||||
return s.rr[i].contains(ip)
|
||||
}
|
||||
|
||||
// ContainsRange reports whether all IPs in r are in s.
|
||||
func (s *IPSet) ContainsRange(r IPRange) bool {
|
||||
for _, x := range s.rr {
|
||||
if r.coveredBy(x) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ContainsPrefix reports whether all IPs in p are in s.
|
||||
func (s *IPSet) ContainsPrefix(p netip.Prefix) bool {
|
||||
return s.ContainsRange(RangeOfPrefix(p))
|
||||
}
|
||||
|
||||
// Overlaps reports whether any IP in b is also in s.
|
||||
func (s *IPSet) Overlaps(b *IPSet) bool {
|
||||
// TODO: sorted ranges lets us do this in O(n+m)
|
||||
for _, r := range s.rr {
|
||||
for _, or := range b.rr {
|
||||
if r.Overlaps(or) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// OverlapsRange reports whether any IP in r is also in s.
|
||||
func (s *IPSet) OverlapsRange(r IPRange) bool {
|
||||
// TODO: sorted ranges lets us do this more efficiently.
|
||||
for _, x := range s.rr {
|
||||
if x.Overlaps(r) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// OverlapsPrefix reports whether any IP in p is also in s.
|
||||
func (s *IPSet) OverlapsPrefix(p netip.Prefix) bool {
|
||||
return s.OverlapsRange(RangeOfPrefix(p))
|
||||
}
|
||||
|
||||
// RemoveFreePrefix splits s into a Prefix of length bitLen and a new
|
||||
// IPSet with that prefix removed.
|
||||
//
|
||||
// If no contiguous prefix of length bitLen exists in s,
|
||||
// RemoveFreePrefix returns ok=false.
|
||||
func (s *IPSet) RemoveFreePrefix(bitLen uint8) (p netip.Prefix, newSet *IPSet, ok bool) {
|
||||
var bestFit netip.Prefix
|
||||
for _, r := range s.rr {
|
||||
for _, prefix := range r.Prefixes() {
|
||||
if uint8(prefix.Bits()) > bitLen {
|
||||
continue
|
||||
}
|
||||
if !bestFit.Addr().IsValid() || prefix.Bits() > bestFit.Bits() {
|
||||
bestFit = prefix
|
||||
if uint8(bestFit.Bits()) == bitLen {
|
||||
// exact match, done.
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !bestFit.Addr().IsValid() {
|
||||
return netip.Prefix{}, s, false
|
||||
}
|
||||
|
||||
prefix := netip.PrefixFrom(bestFit.Addr(), int(bitLen))
|
||||
|
||||
var b IPSetBuilder
|
||||
b.AddSet(s)
|
||||
b.RemovePrefix(prefix)
|
||||
newSet, _ = b.IPSet()
|
||||
return prefix, newSet, true
|
||||
}
|
||||
|
||||
type multiErr []error
|
||||
|
||||
func (e multiErr) Error() string {
|
||||
var ret []string
|
||||
for _, err := range e {
|
||||
ret = append(ret, err.Error())
|
||||
}
|
||||
return strings.Join(ret, "; ")
|
||||
}
|
||||
|
||||
// A stacktraceErr combines an error with a stack trace.
|
||||
type stacktraceErr struct {
|
||||
pcs [16]uintptr // preallocated array of PCs
|
||||
at []uintptr // stack trace whence the error
|
||||
err error // underlying error
|
||||
}
|
||||
|
||||
func (e *stacktraceErr) Error() string {
|
||||
frames := runtime.CallersFrames(e.at)
|
||||
buf := new(strings.Builder)
|
||||
buf.WriteString(e.err.Error())
|
||||
buf.WriteString(" @ ")
|
||||
for {
|
||||
frame, more := frames.Next()
|
||||
if !more {
|
||||
break
|
||||
}
|
||||
fmt.Fprintf(buf, "%s:%d ", frame.File, frame.Line)
|
||||
}
|
||||
return strings.TrimSpace(buf.String())
|
||||
}
|
||||
|
||||
func (e *stacktraceErr) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
141
vendor/go4.org/netipx/mask6.go
generated
vendored
Normal file
141
vendor/go4.org/netipx/mask6.go
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
// Copyright 2021 The Inet.Af AUTHORS. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package netipx
|
||||
|
||||
// mask6 are bitmasks with the topmost n bits of a
|
||||
// 128-bit number, where n is the array index.
|
||||
//
|
||||
// generated with https://play.golang.org/p/64XKxaUSa_9
|
||||
var mask6 = [...]uint128{
|
||||
0: {0x0000000000000000, 0x0000000000000000},
|
||||
1: {0x8000000000000000, 0x0000000000000000},
|
||||
2: {0xc000000000000000, 0x0000000000000000},
|
||||
3: {0xe000000000000000, 0x0000000000000000},
|
||||
4: {0xf000000000000000, 0x0000000000000000},
|
||||
5: {0xf800000000000000, 0x0000000000000000},
|
||||
6: {0xfc00000000000000, 0x0000000000000000},
|
||||
7: {0xfe00000000000000, 0x0000000000000000},
|
||||
8: {0xff00000000000000, 0x0000000000000000},
|
||||
9: {0xff80000000000000, 0x0000000000000000},
|
||||
10: {0xffc0000000000000, 0x0000000000000000},
|
||||
11: {0xffe0000000000000, 0x0000000000000000},
|
||||
12: {0xfff0000000000000, 0x0000000000000000},
|
||||
13: {0xfff8000000000000, 0x0000000000000000},
|
||||
14: {0xfffc000000000000, 0x0000000000000000},
|
||||
15: {0xfffe000000000000, 0x0000000000000000},
|
||||
16: {0xffff000000000000, 0x0000000000000000},
|
||||
17: {0xffff800000000000, 0x0000000000000000},
|
||||
18: {0xffffc00000000000, 0x0000000000000000},
|
||||
19: {0xffffe00000000000, 0x0000000000000000},
|
||||
20: {0xfffff00000000000, 0x0000000000000000},
|
||||
21: {0xfffff80000000000, 0x0000000000000000},
|
||||
22: {0xfffffc0000000000, 0x0000000000000000},
|
||||
23: {0xfffffe0000000000, 0x0000000000000000},
|
||||
24: {0xffffff0000000000, 0x0000000000000000},
|
||||
25: {0xffffff8000000000, 0x0000000000000000},
|
||||
26: {0xffffffc000000000, 0x0000000000000000},
|
||||
27: {0xffffffe000000000, 0x0000000000000000},
|
||||
28: {0xfffffff000000000, 0x0000000000000000},
|
||||
29: {0xfffffff800000000, 0x0000000000000000},
|
||||
30: {0xfffffffc00000000, 0x0000000000000000},
|
||||
31: {0xfffffffe00000000, 0x0000000000000000},
|
||||
32: {0xffffffff00000000, 0x0000000000000000},
|
||||
33: {0xffffffff80000000, 0x0000000000000000},
|
||||
34: {0xffffffffc0000000, 0x0000000000000000},
|
||||
35: {0xffffffffe0000000, 0x0000000000000000},
|
||||
36: {0xfffffffff0000000, 0x0000000000000000},
|
||||
37: {0xfffffffff8000000, 0x0000000000000000},
|
||||
38: {0xfffffffffc000000, 0x0000000000000000},
|
||||
39: {0xfffffffffe000000, 0x0000000000000000},
|
||||
40: {0xffffffffff000000, 0x0000000000000000},
|
||||
41: {0xffffffffff800000, 0x0000000000000000},
|
||||
42: {0xffffffffffc00000, 0x0000000000000000},
|
||||
43: {0xffffffffffe00000, 0x0000000000000000},
|
||||
44: {0xfffffffffff00000, 0x0000000000000000},
|
||||
45: {0xfffffffffff80000, 0x0000000000000000},
|
||||
46: {0xfffffffffffc0000, 0x0000000000000000},
|
||||
47: {0xfffffffffffe0000, 0x0000000000000000},
|
||||
48: {0xffffffffffff0000, 0x0000000000000000},
|
||||
49: {0xffffffffffff8000, 0x0000000000000000},
|
||||
50: {0xffffffffffffc000, 0x0000000000000000},
|
||||
51: {0xffffffffffffe000, 0x0000000000000000},
|
||||
52: {0xfffffffffffff000, 0x0000000000000000},
|
||||
53: {0xfffffffffffff800, 0x0000000000000000},
|
||||
54: {0xfffffffffffffc00, 0x0000000000000000},
|
||||
55: {0xfffffffffffffe00, 0x0000000000000000},
|
||||
56: {0xffffffffffffff00, 0x0000000000000000},
|
||||
57: {0xffffffffffffff80, 0x0000000000000000},
|
||||
58: {0xffffffffffffffc0, 0x0000000000000000},
|
||||
59: {0xffffffffffffffe0, 0x0000000000000000},
|
||||
60: {0xfffffffffffffff0, 0x0000000000000000},
|
||||
61: {0xfffffffffffffff8, 0x0000000000000000},
|
||||
62: {0xfffffffffffffffc, 0x0000000000000000},
|
||||
63: {0xfffffffffffffffe, 0x0000000000000000},
|
||||
64: {0xffffffffffffffff, 0x0000000000000000},
|
||||
65: {0xffffffffffffffff, 0x8000000000000000},
|
||||
66: {0xffffffffffffffff, 0xc000000000000000},
|
||||
67: {0xffffffffffffffff, 0xe000000000000000},
|
||||
68: {0xffffffffffffffff, 0xf000000000000000},
|
||||
69: {0xffffffffffffffff, 0xf800000000000000},
|
||||
70: {0xffffffffffffffff, 0xfc00000000000000},
|
||||
71: {0xffffffffffffffff, 0xfe00000000000000},
|
||||
72: {0xffffffffffffffff, 0xff00000000000000},
|
||||
73: {0xffffffffffffffff, 0xff80000000000000},
|
||||
74: {0xffffffffffffffff, 0xffc0000000000000},
|
||||
75: {0xffffffffffffffff, 0xffe0000000000000},
|
||||
76: {0xffffffffffffffff, 0xfff0000000000000},
|
||||
77: {0xffffffffffffffff, 0xfff8000000000000},
|
||||
78: {0xffffffffffffffff, 0xfffc000000000000},
|
||||
79: {0xffffffffffffffff, 0xfffe000000000000},
|
||||
80: {0xffffffffffffffff, 0xffff000000000000},
|
||||
81: {0xffffffffffffffff, 0xffff800000000000},
|
||||
82: {0xffffffffffffffff, 0xffffc00000000000},
|
||||
83: {0xffffffffffffffff, 0xffffe00000000000},
|
||||
84: {0xffffffffffffffff, 0xfffff00000000000},
|
||||
85: {0xffffffffffffffff, 0xfffff80000000000},
|
||||
86: {0xffffffffffffffff, 0xfffffc0000000000},
|
||||
87: {0xffffffffffffffff, 0xfffffe0000000000},
|
||||
88: {0xffffffffffffffff, 0xffffff0000000000},
|
||||
89: {0xffffffffffffffff, 0xffffff8000000000},
|
||||
90: {0xffffffffffffffff, 0xffffffc000000000},
|
||||
91: {0xffffffffffffffff, 0xffffffe000000000},
|
||||
92: {0xffffffffffffffff, 0xfffffff000000000},
|
||||
93: {0xffffffffffffffff, 0xfffffff800000000},
|
||||
94: {0xffffffffffffffff, 0xfffffffc00000000},
|
||||
95: {0xffffffffffffffff, 0xfffffffe00000000},
|
||||
96: {0xffffffffffffffff, 0xffffffff00000000},
|
||||
97: {0xffffffffffffffff, 0xffffffff80000000},
|
||||
98: {0xffffffffffffffff, 0xffffffffc0000000},
|
||||
99: {0xffffffffffffffff, 0xffffffffe0000000},
|
||||
100: {0xffffffffffffffff, 0xfffffffff0000000},
|
||||
101: {0xffffffffffffffff, 0xfffffffff8000000},
|
||||
102: {0xffffffffffffffff, 0xfffffffffc000000},
|
||||
103: {0xffffffffffffffff, 0xfffffffffe000000},
|
||||
104: {0xffffffffffffffff, 0xffffffffff000000},
|
||||
105: {0xffffffffffffffff, 0xffffffffff800000},
|
||||
106: {0xffffffffffffffff, 0xffffffffffc00000},
|
||||
107: {0xffffffffffffffff, 0xffffffffffe00000},
|
||||
108: {0xffffffffffffffff, 0xfffffffffff00000},
|
||||
109: {0xffffffffffffffff, 0xfffffffffff80000},
|
||||
110: {0xffffffffffffffff, 0xfffffffffffc0000},
|
||||
111: {0xffffffffffffffff, 0xfffffffffffe0000},
|
||||
112: {0xffffffffffffffff, 0xffffffffffff0000},
|
||||
113: {0xffffffffffffffff, 0xffffffffffff8000},
|
||||
114: {0xffffffffffffffff, 0xffffffffffffc000},
|
||||
115: {0xffffffffffffffff, 0xffffffffffffe000},
|
||||
116: {0xffffffffffffffff, 0xfffffffffffff000},
|
||||
117: {0xffffffffffffffff, 0xfffffffffffff800},
|
||||
118: {0xffffffffffffffff, 0xfffffffffffffc00},
|
||||
119: {0xffffffffffffffff, 0xfffffffffffffe00},
|
||||
120: {0xffffffffffffffff, 0xffffffffffffff00},
|
||||
121: {0xffffffffffffffff, 0xffffffffffffff80},
|
||||
122: {0xffffffffffffffff, 0xffffffffffffffc0},
|
||||
123: {0xffffffffffffffff, 0xffffffffffffffe0},
|
||||
124: {0xffffffffffffffff, 0xfffffffffffffff0},
|
||||
125: {0xffffffffffffffff, 0xfffffffffffffff8},
|
||||
126: {0xffffffffffffffff, 0xfffffffffffffffc},
|
||||
127: {0xffffffffffffffff, 0xfffffffffffffffe},
|
||||
128: {0xffffffffffffffff, 0xffffffffffffffff},
|
||||
}
|
||||
584
vendor/go4.org/netipx/netipx.go
generated
vendored
Normal file
584
vendor/go4.org/netipx/netipx.go
generated
vendored
Normal file
@@ -0,0 +1,584 @@
|
||||
// Copyright 2020 The Inet.Af AUTHORS. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package netipx contains code and types that were left behind when
|
||||
// the old inet.af/netaddr package moved to the standard library in Go
|
||||
// 1.18 as net/netip.
|
||||
package netipx // import "go4.org/netipx"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"net/netip"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// FromStdIP returns an IP from the standard library's IP type.
|
||||
//
|
||||
// If std is invalid, ok is false.
|
||||
//
|
||||
// FromStdIP implicitly unmaps IPv6-mapped IPv4 addresses. That is, if
|
||||
// len(std) == 16 and contains an IPv4 address, only the IPv4 part is
|
||||
// returned, without the IPv6 wrapper. This is the common form returned by
|
||||
// the standard library's ParseIP: https://play.golang.org/p/qdjylUkKWxl.
|
||||
// To convert a standard library IP without the implicit unmapping, use
|
||||
// netip.AddrFromSlice.
|
||||
func FromStdIP(std net.IP) (ip netip.Addr, ok bool) {
|
||||
ret, ok := netip.AddrFromSlice(std)
|
||||
return ret.Unmap(), ok
|
||||
}
|
||||
|
||||
// MustFromStdIP is like FromStdIP, but it panics if std is invalid.
|
||||
func MustFromStdIP(std net.IP) netip.Addr {
|
||||
ret, ok := netip.AddrFromSlice(std)
|
||||
if !ok {
|
||||
panic("not a valid IP address")
|
||||
}
|
||||
return ret.Unmap()
|
||||
}
|
||||
|
||||
// FromStdIPRaw returns an IP from the standard library's IP type.
|
||||
// If std is invalid, ok is false.
|
||||
// Unlike FromStdIP, FromStdIPRaw does not do an implicit Unmap if
|
||||
// len(std) == 16 and contains an IPv6-mapped IPv4 address.
|
||||
//
|
||||
// Deprecated: use netip.AddrFromSlice instead.
|
||||
func FromStdIPRaw(std net.IP) (ip netip.Addr, ok bool) {
|
||||
return netip.AddrFromSlice(std)
|
||||
}
|
||||
|
||||
// ParsePrefixOrAddr parses s as an IP address prefix or IP address. If s parses
|
||||
// as an IP address prefix, its [net/netip.Prefix.Addr] is returned. The string
|
||||
// s can be an IPv4 address ("192.0.2.1"), IPv6 address ("2001:db8::68"), IPv4
|
||||
// prefix ("192.0.2.1/32"), or IPv6 prefix ("2001:db:68/96").
|
||||
func ParsePrefixOrAddr(s string) (netip.Addr, error) {
|
||||
// Factored out of netip.ParsePrefix to avoid allocating an empty netip.Prefix in case it's
|
||||
// an address and not a prefix.
|
||||
i := strings.LastIndexByte(s, '/')
|
||||
if i < 0 {
|
||||
return netip.ParseAddr(s)
|
||||
}
|
||||
prefix, err := netip.ParsePrefix(s)
|
||||
return prefix.Addr(), err
|
||||
}
|
||||
|
||||
// AddrNext returns the IP following ip.
|
||||
// If there is none, it returns the IP zero value.
|
||||
//
|
||||
// Deprecated: use netip.Addr.Next instead.
|
||||
func AddrNext(ip netip.Addr) netip.Addr {
|
||||
addr := u128From16(ip.As16()).addOne()
|
||||
if ip.Is4() {
|
||||
if uint32(addr.lo) == 0 {
|
||||
// Overflowed.
|
||||
return netip.Addr{}
|
||||
}
|
||||
return addr.IP4()
|
||||
} else {
|
||||
if addr.isZero() {
|
||||
// Overflowed
|
||||
return netip.Addr{}
|
||||
}
|
||||
return addr.IP6().WithZone(ip.Zone())
|
||||
}
|
||||
}
|
||||
|
||||
// AddrPrior returns the IP before ip.
|
||||
// If there is none, it returns the IP zero value.
|
||||
//
|
||||
// Deprecated: use netip.Addr.Prev instead.
|
||||
func AddrPrior(ip netip.Addr) netip.Addr {
|
||||
addr := u128From16(ip.As16())
|
||||
if ip.Is4() {
|
||||
if uint32(addr.lo) == 0 {
|
||||
return netip.Addr{}
|
||||
}
|
||||
return addr.subOne().IP4()
|
||||
} else {
|
||||
if addr.isZero() {
|
||||
return netip.Addr{}
|
||||
}
|
||||
return addr.subOne().IP6().WithZone(ip.Zone())
|
||||
}
|
||||
}
|
||||
|
||||
// FromStdAddr maps the components of a standard library TCPAddr or
|
||||
// UDPAddr into an IPPort.
|
||||
func FromStdAddr(stdIP net.IP, port int, zone string) (_ netip.AddrPort, ok bool) {
|
||||
ip, ok := FromStdIP(stdIP)
|
||||
if !ok || port < 0 || port > math.MaxUint16 {
|
||||
return netip.AddrPort{}, false
|
||||
}
|
||||
ip = ip.Unmap()
|
||||
if zone != "" {
|
||||
if ip.Is4() {
|
||||
ok = false
|
||||
return
|
||||
}
|
||||
ip = ip.WithZone(zone)
|
||||
}
|
||||
return netip.AddrPortFrom(ip, uint16(port)), true
|
||||
}
|
||||
|
||||
// FromStdIPNet returns an netip.Prefix from the standard library's IPNet type.
|
||||
// If std is invalid, ok is false.
|
||||
func FromStdIPNet(std *net.IPNet) (prefix netip.Prefix, ok bool) {
|
||||
ip, ok := FromStdIP(std.IP)
|
||||
if !ok {
|
||||
return netip.Prefix{}, false
|
||||
}
|
||||
|
||||
if l := len(std.Mask); l != net.IPv4len && l != net.IPv6len {
|
||||
// Invalid mask.
|
||||
return netip.Prefix{}, false
|
||||
}
|
||||
|
||||
ones, bits := std.Mask.Size()
|
||||
if ones == 0 && bits == 0 {
|
||||
// IPPrefix does not support non-contiguous masks.
|
||||
return netip.Prefix{}, false
|
||||
}
|
||||
|
||||
return netip.PrefixFrom(ip, ones), true
|
||||
}
|
||||
|
||||
// RangeOfPrefix returns the inclusive range of IPs that p covers.
|
||||
//
|
||||
// If p is zero or otherwise invalid, Range returns the zero value.
|
||||
func RangeOfPrefix(p netip.Prefix) IPRange {
|
||||
p = p.Masked()
|
||||
if !p.IsValid() {
|
||||
return IPRange{}
|
||||
}
|
||||
return IPRangeFrom(p.Addr(), PrefixLastIP(p))
|
||||
}
|
||||
|
||||
// PrefixIPNet returns the net.IPNet representation of an netip.Prefix.
|
||||
// The returned value is always non-nil.
|
||||
// Any zone identifier is dropped in the conversion.
|
||||
func PrefixIPNet(p netip.Prefix) *net.IPNet {
|
||||
if !p.IsValid() {
|
||||
return &net.IPNet{}
|
||||
}
|
||||
return &net.IPNet{
|
||||
IP: p.Addr().AsSlice(),
|
||||
Mask: net.CIDRMask(p.Bits(), p.Addr().BitLen()),
|
||||
}
|
||||
}
|
||||
|
||||
// AddrIPNet returns the net.IPNet representation of an netip.Addr
|
||||
// with a mask corresponding to the addresses's bit length.
|
||||
// The returned value is always non-nil.
|
||||
// Any zone identifier is dropped in the conversion.
|
||||
func AddrIPNet(addr netip.Addr) *net.IPNet {
|
||||
if !addr.IsValid() {
|
||||
return &net.IPNet{}
|
||||
}
|
||||
return &net.IPNet{
|
||||
IP: addr.AsSlice(),
|
||||
Mask: net.CIDRMask(addr.BitLen(), addr.BitLen()),
|
||||
}
|
||||
}
|
||||
|
||||
// PrefixLastIP returns the last IP in the prefix.
|
||||
func PrefixLastIP(p netip.Prefix) netip.Addr {
|
||||
if !p.IsValid() {
|
||||
return netip.Addr{}
|
||||
}
|
||||
a16 := p.Addr().As16()
|
||||
var off uint8
|
||||
var bits uint8 = 128
|
||||
if p.Addr().Is4() {
|
||||
off = 12
|
||||
bits = 32
|
||||
}
|
||||
for b := uint8(p.Bits()); b < bits; b++ {
|
||||
byteNum, bitInByte := b/8, 7-(b%8)
|
||||
a16[off+byteNum] |= 1 << uint(bitInByte)
|
||||
}
|
||||
if p.Addr().Is4() {
|
||||
return netip.AddrFrom16(a16).Unmap()
|
||||
} else {
|
||||
return netip.AddrFrom16(a16) // doesn't unmap
|
||||
}
|
||||
}
|
||||
|
||||
// IPRange represents an inclusive range of IP addresses
|
||||
// from the same address family.
|
||||
//
|
||||
// The From and To IPs are inclusive bounds, with both included in the
|
||||
// range.
|
||||
//
|
||||
// To be valid, the From and To values must be non-zero, have matching
|
||||
// address families (IPv4 vs IPv6), and From must be less than or equal to To.
|
||||
// IPv6 zones are stripped out and ignored.
|
||||
// An invalid range may be ignored.
|
||||
type IPRange struct {
|
||||
// from is the initial IP address in the range.
|
||||
from netip.Addr
|
||||
|
||||
// to is the final IP address in the range.
|
||||
to netip.Addr
|
||||
}
|
||||
|
||||
// IPRangeFrom returns an IPRange from from to to.
|
||||
// It does not allocate.
|
||||
func IPRangeFrom(from, to netip.Addr) IPRange {
|
||||
return IPRange{
|
||||
from: from.WithZone(""),
|
||||
to: to.WithZone(""),
|
||||
}
|
||||
}
|
||||
|
||||
// From returns the lower bound of r.
|
||||
func (r IPRange) From() netip.Addr { return r.from }
|
||||
|
||||
// To returns the upper bound of r.
|
||||
func (r IPRange) To() netip.Addr { return r.to }
|
||||
|
||||
// ParseIPRange parses a range out of two IPs separated by a hyphen.
|
||||
//
|
||||
// It returns an error if the range is not valid.
|
||||
func ParseIPRange(s string) (IPRange, error) {
|
||||
var r IPRange
|
||||
h := strings.IndexByte(s, '-')
|
||||
if h == -1 {
|
||||
return r, fmt.Errorf("no hyphen in range %q", s)
|
||||
}
|
||||
from, to := s[:h], s[h+1:]
|
||||
var err error
|
||||
r.from, err = netip.ParseAddr(from)
|
||||
if err != nil {
|
||||
return r, fmt.Errorf("invalid From IP %q in range %q", from, s)
|
||||
}
|
||||
r.from = r.from.WithZone("")
|
||||
r.to, err = netip.ParseAddr(to)
|
||||
if err != nil {
|
||||
return r, fmt.Errorf("invalid To IP %q in range %q", to, s)
|
||||
}
|
||||
r.to = r.to.WithZone("")
|
||||
if !r.IsValid() {
|
||||
return r, fmt.Errorf("range %v to %v not valid", r.from, r.to)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// MustParseIPRange calls ParseIPRange(s) and panics on error.
|
||||
// It is intended for use in tests with hard-coded strings.
|
||||
func MustParseIPRange(s string) IPRange {
|
||||
r, err := ParseIPRange(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// String returns a string representation of the range.
|
||||
//
|
||||
// For a valid range, the form is "From-To" with a single hyphen
|
||||
// separating the IPs, the same format recognized by
|
||||
// ParseIPRange.
|
||||
func (r IPRange) String() string {
|
||||
if r.IsValid() {
|
||||
return fmt.Sprintf("%s-%s", r.from, r.to)
|
||||
}
|
||||
if !r.from.IsValid() || !r.to.IsValid() {
|
||||
return "zero IPRange"
|
||||
}
|
||||
return "invalid IPRange"
|
||||
}
|
||||
|
||||
// AppendTo appends a text encoding of r,
|
||||
// as generated by MarshalText,
|
||||
// to b and returns the extended buffer.
|
||||
func (r IPRange) AppendTo(b []byte) []byte {
|
||||
if r.IsZero() {
|
||||
return b
|
||||
}
|
||||
b = r.from.AppendTo(b)
|
||||
b = append(b, '-')
|
||||
b = r.to.AppendTo(b)
|
||||
return b
|
||||
}
|
||||
|
||||
// MarshalText implements the encoding.TextMarshaler interface,
|
||||
// The encoding is the same as returned by String, with one exception:
|
||||
// If ip is the zero value, the encoding is the empty string.
|
||||
func (r IPRange) MarshalText() ([]byte, error) {
|
||||
if r.IsZero() {
|
||||
return []byte(""), nil
|
||||
}
|
||||
var max int
|
||||
if r.from.Is4() {
|
||||
max = len("255.255.255.255-255.255.255.255")
|
||||
} else {
|
||||
max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
|
||||
}
|
||||
b := make([]byte, 0, max)
|
||||
return r.AppendTo(b), nil
|
||||
}
|
||||
|
||||
// UnmarshalText implements the encoding.TextUnmarshaler interface.
|
||||
// The IP range is expected in a form accepted by ParseIPRange.
|
||||
// It returns an error if *r is not the IPRange zero value.
|
||||
func (r *IPRange) UnmarshalText(text []byte) error {
|
||||
if *r != (IPRange{}) {
|
||||
return errors.New("refusing to Unmarshal into non-zero IPRange")
|
||||
}
|
||||
if len(text) == 0 {
|
||||
return nil
|
||||
}
|
||||
var err error
|
||||
*r, err = ParseIPRange(string(text))
|
||||
return err
|
||||
}
|
||||
|
||||
// IsZero reports whether r is the zero value of the IPRange type.
|
||||
func (r IPRange) IsZero() bool {
|
||||
return r == IPRange{}
|
||||
}
|
||||
|
||||
// IsValid reports whether r.From() and r.To() are both non-zero and
|
||||
// obey the documented requirements: address families match, and From
|
||||
// is less than or equal to To.
|
||||
func (r IPRange) IsValid() bool {
|
||||
return r.from.IsValid() &&
|
||||
r.from.BitLen() == r.to.BitLen() &&
|
||||
r.from.Zone() == r.to.Zone() &&
|
||||
!r.to.Less(r.from)
|
||||
}
|
||||
|
||||
// Valid reports whether r.From() and r.To() are both non-zero and
|
||||
// obey the documented requirements: address families match, and From
|
||||
// is less than or equal to To.
|
||||
//
|
||||
// Deprecated: use the correctly named and identical IsValid method instead.
|
||||
func (r IPRange) Valid() bool { return r.IsValid() }
|
||||
|
||||
// Contains reports whether the range r includes addr.
|
||||
//
|
||||
// An invalid range always reports false.
|
||||
//
|
||||
// If ip has an IPv6 zone, Contains returns false,
|
||||
// because IPPrefixes strip zones.
|
||||
func (r IPRange) Contains(addr netip.Addr) bool {
|
||||
return r.IsValid() && addr.Zone() == "" && r.contains(addr)
|
||||
}
|
||||
|
||||
// contains is like Contains, but without the validity check.
|
||||
// addr must not have a zone.
|
||||
func (r IPRange) contains(addr netip.Addr) bool {
|
||||
return r.from.Compare(addr) <= 0 && r.to.Compare(addr) >= 0
|
||||
}
|
||||
|
||||
// less reports whether r is "before" other. It is before if r.From()
|
||||
// is before other.From(). If they're equal, then the larger range
|
||||
// (higher To()) comes first.
|
||||
func (r IPRange) less(other IPRange) bool {
|
||||
if cmp := r.from.Compare(other.from); cmp != 0 {
|
||||
return cmp < 0
|
||||
}
|
||||
return other.to.Less(r.to)
|
||||
}
|
||||
|
||||
// entirelyBefore returns whether r lies entirely before other in IP
|
||||
// space.
|
||||
func (r IPRange) entirelyBefore(other IPRange) bool {
|
||||
return r.to.Less(other.from)
|
||||
}
|
||||
|
||||
func lessOrEq(ip, ip2 netip.Addr) bool { return ip.Compare(ip2) <= 0 }
|
||||
|
||||
// entirelyWithin returns whether r is entirely contained within
|
||||
// other.
|
||||
func (r IPRange) coveredBy(other IPRange) bool {
|
||||
return lessOrEq(other.from, r.from) && lessOrEq(r.to, other.to)
|
||||
}
|
||||
|
||||
// inMiddleOf returns whether r is inside other, but not touching the
|
||||
// edges of other.
|
||||
func (r IPRange) inMiddleOf(other IPRange) bool {
|
||||
return other.from.Less(r.from) && r.to.Less(other.to)
|
||||
}
|
||||
|
||||
// overlapsStartOf returns whether r entirely overlaps the start of
|
||||
// other, but not all of other.
|
||||
func (r IPRange) overlapsStartOf(other IPRange) bool {
|
||||
return lessOrEq(r.from, other.from) && r.to.Less(other.to)
|
||||
}
|
||||
|
||||
// overlapsEndOf returns whether r entirely overlaps the end of
|
||||
// other, but not all of other.
|
||||
func (r IPRange) overlapsEndOf(other IPRange) bool {
|
||||
return other.from.Less(r.from) && lessOrEq(other.to, r.to)
|
||||
}
|
||||
|
||||
// mergeIPRanges returns the minimum and sorted set of IP ranges that
|
||||
// cover r.
|
||||
func mergeIPRanges(rr []IPRange) (out []IPRange, valid bool) {
|
||||
// Always return a copy of r, to avoid aliasing slice memory in
|
||||
// the caller.
|
||||
switch len(rr) {
|
||||
case 0:
|
||||
return nil, true
|
||||
case 1:
|
||||
return []IPRange{rr[0]}, true
|
||||
}
|
||||
|
||||
sort.Slice(rr, func(i, j int) bool { return rr[i].less(rr[j]) })
|
||||
out = make([]IPRange, 1, len(rr))
|
||||
out[0] = rr[0]
|
||||
for _, r := range rr[1:] {
|
||||
prev := &out[len(out)-1]
|
||||
switch {
|
||||
case !r.IsValid():
|
||||
// Invalid ranges make no sense to merge, refuse to
|
||||
// perform.
|
||||
return nil, false
|
||||
case prev.to.Next() == r.from:
|
||||
// prev and r touch, merge them.
|
||||
//
|
||||
// prev r
|
||||
// f------tf-----t
|
||||
prev.to = r.to
|
||||
case prev.to.Less(r.from):
|
||||
// No overlap and not adjacent (per previous case), no
|
||||
// merging possible.
|
||||
//
|
||||
// prev r
|
||||
// f------t f-----t
|
||||
out = append(out, r)
|
||||
case prev.to.Less(r.to):
|
||||
// Partial overlap, update prev
|
||||
//
|
||||
// prev
|
||||
// f------t
|
||||
// f-----t
|
||||
// r
|
||||
prev.to = r.to
|
||||
default:
|
||||
// r entirely contained in prev, nothing to do.
|
||||
//
|
||||
// prev
|
||||
// f--------t
|
||||
// f-----t
|
||||
// r
|
||||
}
|
||||
}
|
||||
return out, true
|
||||
}
|
||||
|
||||
// Overlaps reports whether p and o overlap at all.
|
||||
//
|
||||
// If p and o are of different address families or either are invalid,
|
||||
// it reports false.
|
||||
func (r IPRange) Overlaps(o IPRange) bool {
|
||||
return r.IsValid() &&
|
||||
o.IsValid() &&
|
||||
r.from.Compare(o.to) <= 0 &&
|
||||
o.from.Compare(r.to) <= 0
|
||||
}
|
||||
|
||||
// prefixMaker returns a address-family-corrected IPPrefix from a and bits,
|
||||
// where the input bits is always in the IPv6-mapped form for IPv4 addresses.
|
||||
type prefixMaker func(a uint128, bits uint8) netip.Prefix
|
||||
|
||||
// Prefixes returns the set of IPPrefix entries that covers r.
|
||||
//
|
||||
// If either of r's bounds are invalid, in the wrong order, or if
|
||||
// they're of different address families, then Prefixes returns nil.
|
||||
//
|
||||
// Prefixes necessarily allocates. See AppendPrefixes for a version that uses
|
||||
// memory you provide.
|
||||
func (r IPRange) Prefixes() []netip.Prefix {
|
||||
return r.AppendPrefixes(nil)
|
||||
}
|
||||
|
||||
// AppendPrefixes is an append version of IPRange.Prefixes. It appends
|
||||
// the netip.Prefix entries that cover r to dst.
|
||||
func (r IPRange) AppendPrefixes(dst []netip.Prefix) []netip.Prefix {
|
||||
if !r.IsValid() {
|
||||
return nil
|
||||
}
|
||||
return appendRangePrefixes(dst, r.prefixFrom128AndBits, u128From16(r.from.As16()), u128From16(r.to.As16()))
|
||||
}
|
||||
|
||||
func (r IPRange) prefixFrom128AndBits(a uint128, bits uint8) netip.Prefix {
|
||||
var ip netip.Addr
|
||||
if r.from.Is4() {
|
||||
bits -= 12 * 8
|
||||
ip = a.IP4()
|
||||
} else {
|
||||
ip = a.IP6()
|
||||
}
|
||||
return netip.PrefixFrom(ip, int(bits))
|
||||
}
|
||||
|
||||
// aZeroBSet is whether, after the common bits, a is all zero bits and
|
||||
// b is all set (one) bits.
|
||||
func comparePrefixes(a, b uint128) (common uint8, aZeroBSet bool) {
|
||||
common = a.commonPrefixLen(b)
|
||||
|
||||
// See whether a and b, after their common shared bits, end
|
||||
// in all zero bits or all one bits, respectively.
|
||||
if common == 128 {
|
||||
return common, true
|
||||
}
|
||||
|
||||
m := mask6[common]
|
||||
return common, (a.xor(a.and(m)).isZero() &&
|
||||
b.or(m) == uint128{^uint64(0), ^uint64(0)})
|
||||
}
|
||||
|
||||
// Prefix returns r as an IPPrefix, if it can be presented exactly as such.
|
||||
// If r is not valid or is not exactly equal to one prefix, ok is false.
|
||||
func (r IPRange) Prefix() (p netip.Prefix, ok bool) {
|
||||
if !r.IsValid() {
|
||||
return
|
||||
}
|
||||
from128 := u128From16(r.from.As16())
|
||||
to128 := u128From16(r.to.As16())
|
||||
if common, ok := comparePrefixes(from128, to128); ok {
|
||||
return r.prefixFrom128AndBits(from128, common), true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func appendRangePrefixes(dst []netip.Prefix, makePrefix prefixMaker, a, b uint128) []netip.Prefix {
|
||||
common, ok := comparePrefixes(a, b)
|
||||
if ok {
|
||||
// a to b represents a whole range, like 10.50.0.0/16.
|
||||
// (a being 10.50.0.0 and b being 10.50.255.255)
|
||||
return append(dst, makePrefix(a, common))
|
||||
}
|
||||
// Otherwise recursively do both halves.
|
||||
dst = appendRangePrefixes(dst, makePrefix, a, a.bitsSetFrom(common+1))
|
||||
dst = appendRangePrefixes(dst, makePrefix, b.bitsClearedFrom(common+1), b)
|
||||
return dst
|
||||
}
|
||||
|
||||
// ComparePrefix is a compare function (returning -1, 0 or 1)
|
||||
// sorting prefixes first by address family (IPv4 before IPv6),
|
||||
// then by prefix length (smaller prefixes first), then by
|
||||
// address.
|
||||
func ComparePrefix(a, b netip.Prefix) int {
|
||||
aa, ba := a.Addr(), b.Addr()
|
||||
if al, bl := aa.BitLen(), ba.BitLen(); al != bl {
|
||||
if al < bl {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
ab, bb := a.Bits(), b.Bits()
|
||||
if ab != bb {
|
||||
if ab < bb {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
return aa.Compare(ba)
|
||||
}
|
||||
106
vendor/go4.org/netipx/uint128.go
generated
vendored
Normal file
106
vendor/go4.org/netipx/uint128.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright 2020 The Inet.Af AUTHORS. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package netipx
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math/bits"
|
||||
"net/netip"
|
||||
)
|
||||
|
||||
// uint128 represents a uint128 using two uint64s.
|
||||
//
|
||||
// When the methods below mention a bit number, bit 0 is the most
|
||||
// significant bit (in hi) and bit 127 is the lowest (lo&1).
|
||||
type uint128 struct {
|
||||
hi uint64
|
||||
lo uint64
|
||||
}
|
||||
|
||||
func u128From16(a [16]byte) uint128 {
|
||||
return uint128{
|
||||
binary.BigEndian.Uint64(a[:8]),
|
||||
binary.BigEndian.Uint64(a[8:]),
|
||||
}
|
||||
}
|
||||
|
||||
func (u uint128) IP6() netip.Addr {
|
||||
var a [16]byte
|
||||
binary.BigEndian.PutUint64(a[:8], u.hi)
|
||||
binary.BigEndian.PutUint64(a[8:], u.lo)
|
||||
return netip.AddrFrom16(a)
|
||||
}
|
||||
|
||||
func (u uint128) IP4() netip.Addr {
|
||||
var a [8]byte
|
||||
binary.BigEndian.PutUint64(a[:], u.lo)
|
||||
return netip.AddrFrom4([4]byte{a[4], a[5], a[6], a[7]})
|
||||
}
|
||||
|
||||
// isZero reports whether u == 0.
|
||||
//
|
||||
// It's faster than u == (uint128{}) because the compiler (as of Go
|
||||
// 1.15/1.16b1) doesn't do this trick and instead inserts a branch in
|
||||
// its eq alg's generated code.
|
||||
func (u uint128) isZero() bool { return u.hi|u.lo == 0 }
|
||||
|
||||
// and returns the bitwise AND of u and m (u&m).
|
||||
func (u uint128) and(m uint128) uint128 {
|
||||
return uint128{u.hi & m.hi, u.lo & m.lo}
|
||||
}
|
||||
|
||||
// xor returns the bitwise XOR of u and m (u^m).
|
||||
func (u uint128) xor(m uint128) uint128 {
|
||||
return uint128{u.hi ^ m.hi, u.lo ^ m.lo}
|
||||
}
|
||||
|
||||
// or returns the bitwise OR of u and m (u|m).
|
||||
func (u uint128) or(m uint128) uint128 {
|
||||
return uint128{u.hi | m.hi, u.lo | m.lo}
|
||||
}
|
||||
|
||||
// not returns the bitwise NOT of u.
|
||||
func (u uint128) not() uint128 {
|
||||
return uint128{^u.hi, ^u.lo}
|
||||
}
|
||||
|
||||
// subOne returns u - 1.
|
||||
func (u uint128) subOne() uint128 {
|
||||
lo, borrow := bits.Sub64(u.lo, 1, 0)
|
||||
return uint128{u.hi - borrow, lo}
|
||||
}
|
||||
|
||||
// addOne returns u + 1.
|
||||
func (u uint128) addOne() uint128 {
|
||||
lo, carry := bits.Add64(u.lo, 1, 0)
|
||||
return uint128{u.hi + carry, lo}
|
||||
}
|
||||
|
||||
func u64CommonPrefixLen(a, b uint64) uint8 {
|
||||
return uint8(bits.LeadingZeros64(a ^ b))
|
||||
}
|
||||
|
||||
func (u uint128) commonPrefixLen(v uint128) (n uint8) {
|
||||
if n = u64CommonPrefixLen(u.hi, v.hi); n == 64 {
|
||||
n += u64CommonPrefixLen(u.lo, v.lo)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// func (u *uint128) halves() [2]*uint64 {
|
||||
// return [2]*uint64{&u.hi, &u.lo}
|
||||
// }
|
||||
|
||||
// bitsSetFrom returns a copy of u with the given bit
|
||||
// and all subsequent ones set.
|
||||
func (u uint128) bitsSetFrom(bit uint8) uint128 {
|
||||
return u.or(mask6[bit].not())
|
||||
}
|
||||
|
||||
// bitsClearedFrom returns a copy of u with the given bit
|
||||
// and all subsequent ones cleared.
|
||||
func (u uint128) bitsClearedFrom(bit uint8) uint128 {
|
||||
return u.and(mask6[bit])
|
||||
}
|
||||
Reference in New Issue
Block a user