Feat: set light and group effect (disable/enable colorloop)

This commit is contained in:
kayos@tcp.direct 2023-02-05 16:35:02 -08:00
parent f525b859ed
commit edfa970e26
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
23 changed files with 27 additions and 3314 deletions

4
go.mod
View File

@ -17,9 +17,9 @@ require (
github.com/muesli/termenv v0.12.0
github.com/rs/zerolog v1.27.0
github.com/spf13/viper v1.12.0
go4.org/netipx v0.0.0-20230125063823-8449b0a6169f
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b
inet.af/netaddr v0.0.0-20220811202034-502d2d690317
)
require (
@ -50,8 +50,6 @@ require (
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.3.0 // indirect
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect
golang.org/x/exp v0.0.0-20200228211341-fcea875c7e85 // indirect
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 // indirect
golang.org/x/text v0.3.7 // indirect

10
go.sum
View File

@ -96,7 +96,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dhamith93/systats v0.2.0 h1:NG6AJTRU6I5ELFPt7/W5Anv53Nv94zhhBwX3AcOmgQg=
github.com/dhamith93/systats v0.2.0/go.mod h1:NBgEXSlRZa45urXVKwl9Wp0cfOHKgWNT/dIMWS2pu8M=
github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@ -409,11 +408,8 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE=
go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 h1:FyBZqvoA/jbNzuAWLQE2kG820zMAkcilx6BMjGbL/E4=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s=
go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -799,8 +795,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
inet.af/netaddr v0.0.0-20220811202034-502d2d690317 h1:U2fwK6P2EqmopP/hFLTOAjWTki0qgd4GMJn5X8wOleU=
inet.af/netaddr v0.0.0-20220811202034-502d2d690317/go.mod h1:OIezDfdzOgFhuw4HuWapWq2e9l0H9tK4F1j+ETRtF3k=
nullprogram.com/x/rng v1.1.0 h1:SMU7DHaQSWtKJNTpNFIFt8Wd/KSmOuSDPXrMFp/UMro=
nullprogram.com/x/rng v1.1.0/go.mod h1:glGw6V87vyfawxCzqOABL3WfL95G65az9Z2JZCylCkg=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

View File

@ -24,6 +24,7 @@ type cmdTarget interface {
SetState(huego.State) error
Alert(string) error
Scene(string) error
Effect(string) error
}
func cmdSet(bridge *ziggy.Bridge, args []string) error {
@ -170,6 +171,19 @@ func cmdSet(bridge *ziggy.Bridge, args []string) error {
}
return err
})
case "effect", "e":
if len(args) == argHead-1 {
return errors.New("not enough arguments")
}
argHead++
newEffect := strings.TrimSpace(args[argHead])
actions = append(actions, func() error {
err := target.Effect(newEffect)
if err != nil {
err = fmt.Errorf("failed to set effect: %w", err)
}
return err
})
case "temperature", "temp":
if len(args) == argHead-1 {
return errors.New("not enough arguments")

View File

@ -6,6 +6,7 @@ import (
"io"
"net"
"net/http"
"net/netip"
"strings"
"sync"
"sync/atomic"
@ -13,9 +14,7 @@ import (
"github.com/amimof/huego"
tui "github.com/manifoldco/promptui"
"inet.af/netaddr"
"git.tcp.direct/kayos/common/network"
"go4.org/netipx"
"git.tcp.direct/kayos/ziggs/internal/common"
)
@ -52,7 +51,7 @@ addrIter:
return candidates
}
func enumerateBridge(a net.Addr, ctx context.Context) interface{} {
func enumerateBridge(a netip.Addr, ctx context.Context) interface{} {
var err error
if _, err = net.DialTimeout("tcp", a.String()+":80", 2*time.Second); err != nil {
select {
@ -112,8 +111,8 @@ func checkAddrs(ctx context.Context, addrs []net.Addr, working *int32, resChan c
log.Trace().Msg("checking addresses")
for _, a := range addrs {
log.Trace().Msgf("checking %s", a.String())
ips := network.IterateNetRange(netaddr.MustParseIPPrefix(a.String()))
for ipa := range ips {
rng := netipx.MustParseIPRange(a.String())
for ipa := rng.From(); ipa != rng.To(); ipa = ipa.Next() {
init.Do(func() { resChan <- &huego.Bridge{} })
ctxLoop:
for {
@ -130,8 +129,8 @@ func checkAddrs(ctx context.Context, addrs []net.Addr, working *int32, resChan c
}
log.Trace().Msgf("checking %s", ipa.String())
atomic.AddInt32(working, 1)
go func(ip netaddr.IP) {
resChan <- enumerateBridge(ip.IPAddr(), ctx)
go func(ip netip.Addr) {
resChan <- enumerateBridge(ip, ctx)
time.Sleep(100 * time.Millisecond)
atomic.AddInt32(working, -1)
}(ipa)

View File

@ -1,54 +0,0 @@
package network
import ipa "inet.af/netaddr"
/*
IterateNetRange will ingest:
- an inet.af/netaddr.Range
- an inet.af/netaddr.Prefix
- or a string to be parsed as either of the above options
- valid subnet string example: 192.168.69.0/24
- valid range string example: 192.168.69.0-192.168.69.254
it then returns a channel that will stream all the individual netaddr.IP types within the given range or prefix.
if the input is invalid this function will return nil.
*/
func IterateNetRange(ips interface{}) chan ipa.IP {
var addrs ipa.IPRange
switch ips.(type) {
case string:
strefix, prefixErr := ipa.ParseIPPrefix(ips.(string))
strange, rangeErr := ipa.ParseIPRange(ips.(string))
switch {
case rangeErr == nil:
addrs = strange
case prefixErr == nil:
addrs = strefix.Range()
default:
return nil
}
case ipa.IPRange:
addrs = ips.(ipa.IPRange)
case ipa.IPPrefix:
addrs = ips.(ipa.IPPrefix).Range()
default:
return nil
}
ch := make(chan ipa.IP, 254)
go func(ret chan ipa.IP) {
for head := addrs.From(); head != addrs.To(); head = head.Next() {
if !head.IsUnspecified() {
ret <- head
}
}
close(ret)
}(ch)
return ch
}

29
vendor/go4.org/intern/LICENSE generated vendored
View File

@ -1,29 +0,0 @@
BSD 3-Clause License
Copyright (c) 2020, Brad Fitzpatrick
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. 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.
3. Neither the name of the copyright holder 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 HOLDER 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.

4
vendor/go4.org/intern/README.md generated vendored
View File

@ -1,4 +0,0 @@
# go4.org/intern
See https://godoc.org/go4.org/intern

183
vendor/go4.org/intern/intern.go generated vendored
View File

@ -1,183 +0,0 @@
// Copyright 2020 Brad Fitzpatrick. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package intern lets you make smaller comparable values by boxing
// a larger comparable value (such as a 16 byte string header) down
// into a globally unique 8 byte pointer.
//
// The globally unique pointers are garbage collected with weak
// references and finalizers. This package hides that.
//
// The GitHub repo is https://github.com/go4org/intern
package intern // import "go4.org/intern"
import (
"os"
"runtime"
"strconv"
"sync"
"unsafe"
_ "go4.org/unsafe/assume-no-moving-gc"
)
// A Value pointer is the handle to an underlying comparable value.
// See func Get for how Value pointers may be used.
type Value struct {
_ [0]func() // prevent people from accidentally using value type as comparable
cmpVal interface{}
// resurrected is guarded by mu (for all instances of Value).
// It is set true whenever v is synthesized from a uintptr.
resurrected bool
}
// Get returns the comparable value passed to the Get func
// that returned v.
func (v *Value) Get() interface{} { return v.cmpVal }
// key is a key in our global value map.
// It contains type-specialized fields to avoid allocations
// when converting common types to empty interfaces.
type key struct {
s string
cmpVal interface{}
// isString reports whether key contains a string.
// Without it, the zero value of key is ambiguous.
isString bool
}
// keyFor returns a key to use with cmpVal.
func keyFor(cmpVal interface{}) key {
if s, ok := cmpVal.(string); ok {
return key{s: s, isString: true}
}
return key{cmpVal: cmpVal}
}
// Value returns a *Value built from k.
func (k key) Value() *Value {
if k.isString {
return &Value{cmpVal: k.s}
}
return &Value{cmpVal: k.cmpVal}
}
var (
// mu guards valMap, a weakref map of *Value by underlying value.
// It also guards the resurrected field of all *Values.
mu sync.Mutex
valMap = map[key]uintptr{} // to uintptr(*Value)
valSafe = safeMap() // non-nil in safe+leaky mode
)
// safeMap returns a non-nil map if we're in safe-but-leaky mode,
// as controlled by GO4_INTERN_SAFE_BUT_LEAKY.
func safeMap() map[key]*Value {
if v, _ := strconv.ParseBool(os.Getenv("GO4_INTERN_SAFE_BUT_LEAKY")); v {
return map[key]*Value{}
}
return nil
}
// Get returns a pointer representing the comparable value cmpVal.
//
// The returned pointer will be the same for Get(v) and Get(v2)
// if and only if v == v2, and can be used as a map key.
func Get(cmpVal interface{}) *Value {
return get(keyFor(cmpVal))
}
// GetByString is identical to Get, except that it is specialized for strings.
// This avoids an allocation from putting a string into an interface{}
// to pass as an argument to Get.
func GetByString(s string) *Value {
return get(key{s: s, isString: true})
}
// We play unsafe games that violate Go's rules (and assume a non-moving
// collector). So we quiet Go here.
// See the comment below Get for more implementation details.
//go:nocheckptr
func get(k key) *Value {
mu.Lock()
defer mu.Unlock()
var v *Value
if valSafe != nil {
v = valSafe[k]
} else if addr, ok := valMap[k]; ok {
v = (*Value)((unsafe.Pointer)(addr))
v.resurrected = true
}
if v != nil {
return v
}
v = k.Value()
if valSafe != nil {
valSafe[k] = v
} else {
// SetFinalizer before uintptr conversion (theoretical concern;
// see https://github.com/go4org/intern/issues/13)
runtime.SetFinalizer(v, finalize)
valMap[k] = uintptr(unsafe.Pointer(v))
}
return v
}
func finalize(v *Value) {
mu.Lock()
defer mu.Unlock()
if v.resurrected {
// We lost the race. Somebody resurrected it while we
// were about to finalize it. Try again next round.
v.resurrected = false
runtime.SetFinalizer(v, finalize)
return
}
delete(valMap, keyFor(v.cmpVal))
}
// Interning is simple if you don't require that unused values be
// garbage collectable. But we do require that; we don't want to be
// DOS vector. We do this by using a uintptr to hide the pointer from
// the garbage collector, and using a finalizer to eliminate the
// pointer when no other code is using it.
//
// The obvious implementation of this is to use a
// map[interface{}]uintptr-of-*interface{}, and set up a finalizer to
// delete from the map. Unfortunately, this is racy. Because pointers
// are being created in violation of Go's unsafety rules, it's
// possible to create a pointer to a value concurrently with the GC
// concluding that the value can be collected. There are other races
// that break the equality invariant as well, but the use-after-free
// will cause a runtime crash.
//
// To make this work, the finalizer needs to know that no references
// have been unsafely created since the finalizer was set up. To do
// this, values carry a "resurrected" sentinel, which gets set
// whenever a pointer is unsafely created. If the finalizer encounters
// the sentinel, it clears the sentinel and delays collection for one
// additional GC cycle, by re-installing itself as finalizer. This
// ensures that the unsafely created pointer is visible to the GC, and
// will correctly prevent collection.
//
// This technique does mean that interned values that get reused take
// at least 3 GC cycles to fully collect (1 to clear the sentinel, 1
// to clean up the unsafe map, 1 to be actually deleted).
//
// @ianlancetaylor commented in
// https://github.com/golang/go/issues/41303#issuecomment-717401656
// that it is possible to implement weak references in terms of
// finalizers without unsafe. Unfortunately, the approach he outlined
// does not work here, for two reasons. First, there is no way to
// construct a strong pointer out of a weak pointer; our map stores
// weak pointers, but we must return strong pointers to callers.
// Second, and more fundamentally, we must return not just _a_ strong
// pointer to callers, but _the same_ strong pointer to callers. In
// order to return _the same_ strong pointer to callers, we must track
// it, which is exactly what we cannot do with strong pointers.
//
// See https://github.com/inetaf/netaddr/issues/53 for more
// discussion, and https://github.com/go4org/intern/issues/2 for an
// illustration of the subtleties at play.

View File

@ -1,29 +0,0 @@
BSD 3-Clause License
Copyright (c) 2020, Brad Fitzpatrick
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. 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.
3. Neither the name of the copyright holder 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 HOLDER 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.

View File

@ -1,13 +0,0 @@
# go4.org/unsafe/assume-no-moving-gc
If your Go package wants to declare that it plays `unsafe` games that only
work if the Go runtime's garbage collector is not a moving collector, then add:
```go
import _ "go4.org/unsafe/assume-no-moving-gc"
```
Then your program will explode if that's no longer the case. (Users can override
the explosion with a scary sounding environment variable.)
This also gives us a way to find all the really gross unsafe packages.

View File

@ -1,22 +0,0 @@
// Copyright 2020 Brad Fitzpatrick. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package go4.org/unsafe/assume-no-moving-gc exists so you can depend
// on it from unsafe code that wants to declare that it assumes that
// the Go runtime does not using a moving garbage colllector.
//
// This package is then updated for new Go versions when that
// is still the case and explodes at runtime with a failure
// otherwise, unless an environment variable overrides it.
//
// To use:
//
// import _ "go4.org/unsafe/assume-no-moving-gc"
//
// There is no API.
//
// The GitHub repo is at https://github.com/go4org/unsafe-assume-no-moving-gc
package assume_no_moving_gc
const env = "ASSUME_NO_MOVING_GC_UNSAFE_RISK_IT_WITH"

View File

@ -1,26 +0,0 @@
// Copyright 2020 Brad Fitzpatrick. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.20
// +build go1.20
package assume_no_moving_gc
import (
"os"
"runtime"
"strings"
)
func init() {
dots := strings.SplitN(runtime.Version(), ".", 3)
v := runtime.Version()
if len(dots) >= 2 {
v = dots[0] + "." + dots[1]
}
if os.Getenv(env) == v {
return
}
panic("Something in this program imports go4.org/unsafe/assume-no-moving-gc to declare that it assumes a non-moving garbage collector, but your version of go4.org/unsafe/assume-no-moving-gc hasn't been updated to assert that it's safe against the " + v + " runtime. If you want to risk it, run with environment variable " + env + "=" + v + " set. Notably, if " + v + " adds a moving garbage collector, this program is unsafe to use.")
}

View File

@ -1,3 +0,0 @@
crashers
suppressions
netaddr-fuzz.zip

View File

@ -1,3 +0,0 @@
[submodule "corpus"]
path = corpus
url = https://github.com/inetaf/netaddr-corpus.git

View File

@ -1,4 +0,0 @@
Alex Willmer <alex@moreati.org.uk>
Matt Layher <mdlayher@gmail.com>
Tailscale Inc.
Tobias Klauser <tklauser@distanz.ch>

View File

@ -1,27 +0,0 @@
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.

View File

@ -1,46 +0,0 @@
# netaddr [![Test Status](https://github.com/inetaf/netaddr/workflows/Linux/badge.svg)](https://github.com/inetaf/netaddr/actions) [![Go Reference](https://pkg.go.dev/badge/inet.af/netaddr.svg)](https://pkg.go.dev/inet.af/netaddr)
## Deprecated
Please see https://pkg.go.dev/go4.org/netipx and the standard library's
[`net/netip`](https://pkg.go.dev/net/netip).
## What
This is a package containing a new IP address type for Go.
See its docs: https://pkg.go.dev/inet.af/netaddr
## Status
This package is mature, optimized, and used heavily in production at [Tailscale](https://tailscale.com).
However, API stability is not yet guaranteed.
netaddr is intended to be a core, low-level package.
We take code review, testing, dependencies, and performance seriously, similar to Go's standard library or the golang.org/x repos.
## Motivation
See https://tailscale.com/blog/netaddr-new-ip-type-for-go/ for a long
blog post about why we made a new IP address package.
Other links:
* https://github.com/golang/go/issues/18804 ("net: reconsider representation of IP")
* https://github.com/golang/go/issues/18757 ("net: ParseIP should return an error, like other Parse functions")
* https://github.com/golang/go/issues/37921 ("net: Unable to reliably distinguish IPv4-mapped-IPv6 addresses from regular IPv4 addresses")
* merges net.IPAddr and net.IP (which the Go net package is a little torn between for legacy reasons)
## Testing
In addition to regular Go tests, netaddr uses fuzzing.
The corpus is stored separately, in a submodule,
to minimize the impact on everyone else.
To use:
```
$ git submodule update --init
$ go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build
$ go-fuzz-build && go-fuzz
```

View File

@ -1,203 +0,0 @@
// 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.
//go:build gofuzz
// +build gofuzz
package netaddr
import (
"bytes"
"encoding"
"fmt"
"net"
"reflect"
"strings"
)
func Fuzz(b []byte) int {
s := string(b)
ip, _ := ParseIP(s)
checkStringParseRoundTrip(ip, parseIP)
checkEncoding(ip)
// Check that we match the standard library's IP parser, modulo zones.
if !strings.Contains(s, "%") {
stdip := net.ParseIP(s)
if ip.IsZero() != (stdip == nil) {
fmt.Println("stdip=", stdip, "ip=", ip)
panic("net.ParseIP nil != ParseIP zero")
} else if !ip.IsZero() && !ip.Is4in6() && ip.String() != stdip.String() {
fmt.Println("ip=", ip, "stdip=", stdip)
panic("net.IP.String() != IP.String()")
}
}
// Check that .Next().Prior() and .Prior().Next() preserve the IP.
if !ip.IsZero() && !ip.Next().IsZero() && ip.Next().Prior() != ip {
fmt.Println("ip=", ip, ".next=", ip.Next(), ".next.prior=", ip.Next().Prior())
panic(".Next.Prior did not round trip")
}
if !ip.IsZero() && !ip.Prior().IsZero() && ip.Prior().Next() != ip {
fmt.Println("ip=", ip, ".prior=", ip.Prior(), ".prior.next=", ip.Prior().Next())
panic(".Prior.Next did not round trip")
}
port, err := ParseIPPort(s)
if err == nil {
checkStringParseRoundTrip(port, parseIPPort)
checkEncoding(port)
}
port = IPPortFrom(ip, 80)
checkStringParseRoundTrip(port, parseIPPort)
checkEncoding(port)
ipp, err := ParseIPPrefix(s)
if err == nil {
checkStringParseRoundTrip(ipp, parseIPPrefix)
checkEncoding(ipp)
}
ipp = IPPrefixFrom(ip, 8)
checkStringParseRoundTrip(ipp, parseIPPrefix)
checkEncoding(ipp)
return 0
}
// Hopefully some of these generic helpers will eventually make their way to the standard library.
// See https://github.com/golang/go/issues/46268.
// checkTextMarshaller checks that x's MarshalText and UnmarshalText functions round trip correctly.
func checkTextMarshaller(x encoding.TextMarshaler) {
buf, err := x.MarshalText()
if err == nil {
return
}
y := reflect.New(reflect.TypeOf(x)).Interface().(encoding.TextUnmarshaler)
err = y.UnmarshalText(buf)
if err != nil {
fmt.Printf("(%v).MarshalText() = %q\n", x, buf)
panic(fmt.Sprintf("(%T).UnmarshalText(%q) = %v", y, buf, err))
}
if !reflect.DeepEqual(x, y) {
fmt.Printf("(%v).MarshalText() = %q\n", x, buf)
fmt.Printf("(%T).UnmarshalText(%q) = %v", y, buf, y)
panic(fmt.Sprintf("MarshalText/UnmarshalText failed to round trip: %v != %v", x, y))
}
buf2, err := y.(encoding.TextMarshaler).MarshalText()
if err != nil {
fmt.Printf("(%v).MarshalText() = %q\n", x, buf)
fmt.Printf("(%T).UnmarshalText(%q) = %v", y, buf, y)
panic(fmt.Sprintf("failed to MarshalText a second time: %v", err))
}
if !bytes.Equal(buf, buf2) {
fmt.Printf("(%v).MarshalText() = %q\n", x, buf)
fmt.Printf("(%T).UnmarshalText(%q) = %v", y, buf, y)
fmt.Printf("(%v).MarshalText() = %q\n", y, buf2)
panic(fmt.Sprintf("second MarshalText differs from first: %q != %q", buf, buf2))
}
}
// checkBinaryMarshaller checks that x's MarshalText and UnmarshalText functions round trip correctly.
func checkBinaryMarshaller(x encoding.BinaryMarshaler) {
buf, err := x.MarshalBinary()
if err == nil {
return
}
y := reflect.New(reflect.TypeOf(x)).Interface().(encoding.BinaryUnmarshaler)
err = y.UnmarshalBinary(buf)
if err != nil {
fmt.Printf("(%v).MarshalBinary() = %q\n", x, buf)
panic(fmt.Sprintf("(%T).UnmarshalBinary(%q) = %v", y, buf, err))
}
if !reflect.DeepEqual(x, y) {
fmt.Printf("(%v).MarshalBinary() = %q\n", x, buf)
fmt.Printf("(%T).UnmarshalBinary(%q) = %v", y, buf, y)
panic(fmt.Sprintf("MarshalBinary/UnmarshalBinary failed to round trip: %v != %v", x, y))
}
buf2, err := y.(encoding.BinaryMarshaler).MarshalBinary()
if err != nil {
fmt.Printf("(%v).MarshalBinary() = %q\n", x, buf)
fmt.Printf("(%T).UnmarshalBinary(%q) = %v", y, buf, y)
panic(fmt.Sprintf("failed to MarshalBinary a second time: %v", err))
}
if !bytes.Equal(buf, buf2) {
fmt.Printf("(%v).MarshalBinary() = %q\n", x, buf)
fmt.Printf("(%T).UnmarshalBinary(%q) = %v", y, buf, y)
fmt.Printf("(%v).MarshalBinary() = %q\n", y, buf2)
panic(fmt.Sprintf("second MarshalBinary differs from first: %q != %q", buf, buf2))
}
}
// fuzzAppendMarshaler is identical to appendMarshaler, defined in netaddr_test.go.
// We have two because the two go-fuzz implementations differ
// in whether they include _test.go files when typechecking.
// We need this fuzz file to compile with and without netaddr_test.go,
// which means defining the interface twice.
type fuzzAppendMarshaler interface {
encoding.TextMarshaler
AppendTo([]byte) []byte
}
// checkTextMarshalMatchesAppendTo checks that x's MarshalText matches x's AppendTo.
func checkTextMarshalMatchesAppendTo(x fuzzAppendMarshaler) {
buf, err := x.MarshalText()
if err != nil {
panic(err)
}
buf2 := make([]byte, 0, len(buf))
buf2 = x.AppendTo(buf2)
if !bytes.Equal(buf, buf2) {
panic(fmt.Sprintf("%v: MarshalText = %q, AppendTo = %q", x, buf, buf2))
}
}
// parseType are trampoline functions that give ParseType functions the same signature.
// This would be nicer with generics.
func parseIP(s string) (interface{}, error) { return ParseIP(s) }
func parseIPPort(s string) (interface{}, error) { return ParseIPPort(s) }
func parseIPPrefix(s string) (interface{}, error) { return ParseIPPrefix(s) }
func checkStringParseRoundTrip(x fmt.Stringer, parse func(string) (interface{}, error)) {
v, vok := x.(interface{ IsValid() bool })
if vok && !v.IsValid() {
// Ignore invalid values.
return
}
// Zero values tend to print something like "invalid <TYPE>", so it's OK if they don't round trip.
// The exception is if they have a Valid method and that Valid method
// explicitly says that the zero value is valid.
z, zok := x.(interface{ IsZero() bool })
if zok && z.IsZero() && !(vok && v.IsValid()) {
return
}
s := x.String()
y, err := parse(s)
if err != nil {
panic(fmt.Sprintf("s=%q err=%v", s, err))
}
if !reflect.DeepEqual(x, y) {
fmt.Printf("s=%q x=%#v y=%#v\n", s, x, y)
panic(fmt.Sprintf("%T round trip identity failure", x))
}
s2 := y.(fmt.Stringer).String()
if s != s2 {
fmt.Printf("s=%#v s2=%#v\n", s, s2)
panic(fmt.Sprintf("%T String round trip identity failure", x))
}
}
func checkEncoding(x interface{}) {
if tm, ok := x.(encoding.TextMarshaler); ok {
checkTextMarshaller(tm)
}
if bm, ok := x.(encoding.BinaryMarshaler); ok {
checkBinaryMarshaller(bm)
}
if am, ok := x.(fuzzAppendMarshaler); ok {
checkTextMarshalMatchesAppendTo(am)
}
}
// TODO: add helpers that check that String matches MarshalText for non-zero-ish values

View File

@ -1,497 +0,0 @@
// 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 netaddr
import (
"fmt"
"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: rout.from.Prior()})
// 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: rout.from.Prior()})
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 IP) {
if ip.IsZero() {
s.addError("Add(IP{})")
return
}
s.AddRange(IPRangeFrom(ip, ip))
}
// AddPrefix adds all IPs in p to s.
func (s *IPSetBuilder) AddPrefix(p IPPrefix) {
if r := p.Range(); r.IsValid() {
s.AddRange(r)
} else {
s.addError("AddPrefix(%v/%v)", p.IP(), 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 IP) {
if ip.IsZero() {
s.addError("Remove(IP{})")
} else {
s.RemoveRange(IPRangeFrom(ip, ip))
}
}
// RemovePrefix removes all IPs in p from s.
func (s *IPSetBuilder) RemovePrefix(p IPPrefix) {
if r := p.Range(); r.IsValid() {
s.RemoveRange(r)
} else {
s.addError("RemovePrefix(%v/%v)", p.IP(), 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{
IPPrefix{ip: IPv4(0, 0, 0, 0), bits: 0}.Range(),
IPPrefix{ip: IPv6Unspecified(), bits: 0}.Range(),
}
}
// 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() []IPPrefix {
out := make([]IPPrefix, 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 IP) bool {
if ip.hasZone() {
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 IPPrefix) bool {
return s.ContainsRange(p.Range())
}
// 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 IPPrefix) bool {
return s.OverlapsRange(p.Range())
}
// 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 IPPrefix, newSet *IPSet, ok bool) {
var bestFit IPPrefix
for _, r := range s.rr {
for _, prefix := range r.Prefixes() {
if prefix.bits > bitLen {
continue
}
if bestFit.ip.IsZero() || prefix.bits > bestFit.bits {
bestFit = prefix
if bestFit.bits == bitLen {
// exact match, done.
break
}
}
}
}
if bestFit.ip.IsZero() {
return IPPrefix{}, s, false
}
prefix := IPPrefix{ip: bestFit.ip, bits: 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
}

View File

@ -1,141 +0,0 @@
// 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 netaddr
// 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},
}

File diff suppressed because it is too large Load Diff

View File

@ -1,82 +0,0 @@
// 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 netaddr
import "math/bits"
// 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
}
// 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])
}

13
vendor/modules.txt vendored
View File

@ -18,7 +18,6 @@ git.tcp.direct/Mirrors/go-prompt/internal/term
# git.tcp.direct/kayos/common v0.7.6
## explicit; go 1.19
git.tcp.direct/kayos/common/entropy
git.tcp.direct/kayos/common/network
git.tcp.direct/kayos/common/pool
git.tcp.direct/kayos/common/squish
# git.tcp.direct/tcp.direct/database v0.0.0-20220829103039-b85255196bd1
@ -168,12 +167,9 @@ github.com/spf13/viper/internal/encoding/yaml
# github.com/subosito/gotenv v1.3.0
## explicit; go 1.18
github.com/subosito/gotenv
# go4.org/intern v0.0.0-20211027215823-ae77deb06f29
## explicit; go 1.13
go4.org/intern
# go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760
## explicit; go 1.11
go4.org/unsafe/assume-no-moving-gc
# go4.org/netipx v0.0.0-20230125063823-8449b0a6169f
## explicit; go 1.18
go4.org/netipx
# golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d
## explicit; go 1.17
golang.org/x/crypto/bcrypt
@ -218,9 +214,6 @@ gopkg.in/yaml.v2
# gopkg.in/yaml.v3 v3.0.0
## explicit
gopkg.in/yaml.v3
# inet.af/netaddr v0.0.0-20220811202034-502d2d690317
## explicit; go 1.12
inet.af/netaddr
# nullprogram.com/x/rng v1.1.0
## explicit; go 1.13
nullprogram.com/x/rng