func (prefix DevAddrPrefix) String() string {
	return fmt.Sprintf("%s/%d", prefix.DevAddr, prefix.Length)
}
String implements the Stringer interface.
package types
import (
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"strconv"
	"strings"
	"github.com/TheThingsIndustries/protoc-gen-go-json/jsonplugin"
	"go.thethings.network/lorawan-stack/v3/pkg/errors"
)
var errInvalidDevAddr = errors.DefineInvalidArgument("invalid_dev_addr", "invalid DevAddr")
type DevAddr [4]byte
var MinDevAddr = DevAddr{0x00, 0x00, 0x00, 0x00}
var MaxDevAddr = DevAddr{0xFF, 0xFF, 0xFF, 0xFF}
func (addr DevAddr) IsZero() bool { return addr == [4]byte{} }
func (addr DevAddr) String() string { return strings.ToUpper(hex.EncodeToString(addr[:])) }
func (addr DevAddr) GoString() string { return addr.String() }
func (addr DevAddr) Size() int { return 4 }
func (addr DevAddr) Equal(other DevAddr) bool { return addr == other }
func (addr DevAddr) Marshal() ([]byte, error) { return addr.MarshalBinary() }
func (addr DevAddr) MarshalTo(data []byte) (int, error) { return marshalBinaryBytesTo(data, addr[:]) }
func (addr *DevAddr) Unmarshal(data []byte) error { return addr.UnmarshalBinary(data) }
func (addr DevAddr) MarshalJSON() ([]byte, error) { return marshalJSONHexBytes(addr[:]) }
func (addr *DevAddr) UnmarshalJSON(data []byte) error {
	*addr = [4]byte{}
	if err := unmarshalJSONHexBytes(addr[:], data); err != nil {
		return errInvalidDevAddr.WithCause(err)
	}
	return nil
}
func (addr *DevAddr) MarshalProtoJSON(s *jsonplugin.MarshalState) {
	if addr == nil {
		s.WriteNil()
		return
	}
	s.WriteString(fmt.Sprintf("%X", addr[:]))
}
func (addr *DevAddr) UnmarshalProtoJSON(s *jsonplugin.UnmarshalState) {
	*addr = [4]byte{}
	b, err := hex.DecodeString(s.ReadString())
	if err != nil {
		s.SetError(err)
		return
	}
	if len(b) != 4 {
		s.SetError(errInvalidDevAddr.WithCause(errInvalidLength.WithAttributes("want", 4, "got", len(b))))
		return
	}
	copy(addr[:], b)
}
func (addr DevAddr) MarshalBinary() ([]byte, error) { return marshalBinaryBytes(addr[:]) }
func (addr *DevAddr) UnmarshalBinary(data []byte) error {
	*addr = [4]byte{}
	if err := unmarshalBinaryBytes(addr[:], data); err != nil {
		return errInvalidDevAddr.WithCause(err)
	}
	return nil
}
func (addr DevAddr) MarshalText() ([]byte, error) { return marshalTextBytes(addr[:]) }
func (addr *DevAddr) UnmarshalText(data []byte) error {
	*addr = [4]byte{}
	if err := unmarshalTextBytes(addr[:], data); err != nil {
		return errInvalidDevAddr.WithCause(err)
	}
	return nil
}
func (addr DevAddr) MarshalNumber() uint32 {
	return binary.BigEndian.Uint32(addr[:])
}
func (addr *DevAddr) UnmarshalNumber(n uint32) {
	*addr = [4]byte{}
	binary.BigEndian.PutUint32(addr[:], n)
}
func (addr DevAddr) HasValidNetIDType() bool {
	return addr[0] != 0xff
}
func (addr DevAddr) NetIDType() byte {
	for i := uint(7); i >= 0; i-- {
		if addr[0]&(1<<i) == 0 {
			return byte(7 - i)
		}
	}
	panic(unmatchedNetID)
}
func (addr DevAddr) NwkAddr() []byte {
	switch addr.NetIDType() {
	case 0:
		return []byte{addr[0] & 0x01, addr[1], addr[2], addr[3]}
	case 1:
		return []byte{addr[1], addr[2], addr[3]}
	case 2:
		return []byte{addr[1] & 0x0f, addr[2], addr[3]}
	case 3:
		return []byte{addr[1] & 0x01, addr[2], addr[3]}
	case 4:
		return []byte{addr[2] & 0x7f, addr[3]}
	case 5:
		return []byte{addr[2] & 0x1f, addr[3]}
	case 6:
		return []byte{addr[2] & 0x03, addr[3]}
	case 7:
		return []byte{addr[3] & 0x7f}
	}
	panic(unmatchedNetID)
}
func (addr DevAddr) NwkID() []byte {
	switch addr.NetIDType() {
	case 0:
		return []byte{(addr[0] & 0x7f) >> 1}
	case 1:
		return []byte{addr[0] & 0x3f}
	case 2:
		return []byte{(addr[0] & 0x1f) >> 4, (addr[0] << 4) | (addr[1] >> 4)}
	case 3:
		return []byte{(addr[0] >> 1) & 0x07, (addr[0] << 7) | (addr[1] >> 1)}
	case 4:
		return []byte{((addr[0] & 0x07) << 1) | (addr[1] >> 7), (addr[1] << 1) | (addr[2] >> 7)}
	case 5:
		return []byte{((addr[0] & 0x03) << 3) | (addr[1] >> 5), (addr[1] << 3) | (addr[2] >> 5)}
	case 6:
		return []byte{((addr[0] & 0x01) << 6) | (addr[1] >> 2), (addr[1] << 6) | (addr[2] >> 2)}
	case 7:
		return []byte{addr[1] >> 7, (addr[1] << 1) | (addr[2] >> 7), (addr[2] << 1) | (addr[3] >> 7)}
	}
	panic(unmatchedNetID)
}
func NwkAddrBits(netID NetID) uint {
	switch netID.Type() {
	case 0:
		return 25
	case 1:
		return 24
	case 2:
		return 20
	case 3:
		return 17
	case 4:
		return 15
	case 5:
		return 13
	case 6:
		return 10
	case 7:
		return 7
	}
	panic(unmatchedNetID)
}
func NwkAddrLength(netID NetID) int {
	return int((NwkAddrBits(netID) + 7) / 8)
}
var errNwkAddrLength = errors.DefineInternal("nwk_addr_bits", "too many bits set in NwkAddr")
func NewDevAddr(netID NetID, nwkAddr []byte) (addr DevAddr, err error) {
	if len(nwkAddr) < 4 {
		nwkAddr = append(make([]byte, 4-len(nwkAddr)), nwkAddr...)
	}
	if nwkAddr[0]&(0xfe<<((NwkAddrBits(netID)-1)%8)) > 0 {
		return DevAddr{}, errNwkAddrLength.New()
	}
	copy(addr[:], nwkAddr)
	nwkID := netID.ID()
	t := netID.Type()
	switch t {
	case 0:
		addr[0] |= nwkID[0] << 1
	case 1:
		addr[0] |= nwkID[0]
	case 2:
		addr[1] |= nwkID[1] << 4
		addr[0] |= nwkID[1] >> 4
		addr[0] |= nwkID[0] << 4
	case 3:
		addr[1] |= nwkID[2] << 1
		addr[0] |= nwkID[2] >> 7
		addr[0] |= nwkID[1] << 1
	case 4:
		addr[2] |= nwkID[2] << 7
		addr[1] |= nwkID[2] >> 1
		addr[1] |= nwkID[1] << 7
		addr[0] |= nwkID[1] >> 1
	case 5:
		addr[2] |= nwkID[2] << 5
		addr[1] |= nwkID[2] >> 3
		addr[1] |= nwkID[1] << 5
		addr[0] |= nwkID[1] >> 3
	case 6:
		addr[2] |= nwkID[2] << 2
		addr[1] |= nwkID[2] >> 6
		addr[1] |= nwkID[1] << 2
		addr[0] |= nwkID[1] >> 6
	case 7:
		addr[3] |= nwkID[2] << 7
		addr[2] |= nwkID[2] >> 1
		addr[2] |= nwkID[1] << 7
		addr[1] |= nwkID[1] >> 1
		addr[1] |= nwkID[0] << 7
	}
	addr[0] |= 0xfe << (7 - t)
	return addr, nil
}
type DevAddrPrefix struct {
	DevAddr DevAddr
	Length  uint8
}
func (prefix DevAddrPrefix) IsZero() bool { return prefix.Length == 0 }