/* * Cmp compares to c4ids. * There are 3 possible return values. * -1 : Argument id is less than calling id. * 0: Argument id and calling id are identical. * +1: Argument id is greater than calling id. * Comparison is done on the actual numerical value of the ids. * Not the string representation. */ func (x *ID) Cmp(y *ID) int { if y == nil { return -1 } bigX := big.Int(*x) bigY := big.Int(*y) return bigX.Cmp(&bigY) }
// ListenStreamArgs returns the arguments required to be passed to // net.ListenTCP(). If the Mask of ipv6 is not a /128, ListenStreamArgs() // will fail. See Host() to create an IPv6Addr with its mask set to /128. func (ipv6 IPv6Addr) ListenStreamArgs() (network, listenArgs string) { ipv6Mask := big.Int(*ipv6.Mask) if ipv6Mask.Cmp(ipv6HostMask) != 0 { return "tcp6", "" } return "tcp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port) }
// DialPacketArgs returns the arguments required to be passed to // net.DialUDP(). If the Mask of ipv6 is not a /128 or the Port is 0, // DialPacketArgs() will fail. See Host() to create an IPv6Addr with its // mask set to /128. func (ipv6 IPv6Addr) DialPacketArgs() (network, dialArgs string) { ipv6Mask := big.Int(*ipv6.Mask) if ipv6Mask.Cmp(ipv6HostMask) != 0 || ipv6.Port == 0 { return "udp6", "" } return "udp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port) }
// MarshalJSON adds output support for package encoding/json. func (id *ID) MarshalJSON() ([]byte, error) { bigID := big.Int(*id) if bigID.Cmp(big.NewInt(0)) == 0 { return []byte(`""`), nil } return []byte(`"` + id.String() + `"`), nil }
func TestAppendOrder(t *testing.T) { is := is.New(t) byteData := [4][]byte{ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0d, 0x24}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0xfa, 0x28}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xac, 0xad, 0x10}, } expectedIDs := [4]string{ `c41111111111111111111111111111111111111111111111111111111111111111111111111111111111111121`, `c41111111111111111111111111111111111111111111111111111111111111111111111111111111111111211`, `c41111111111111111111111111111111111111111111111111111111111111111111111111111111111112111`, `c41111111111111111111111111111111111111111111111111111111111111111111111111111111111121111`, } for k := 0; k < 4; k++ { b := byteData[k] bignum := big.NewInt(0) bignum = bignum.SetBytes(b) id := asset.ID(*bignum) is.Equal(id.String(), expectedIDs[k]) id2, err := asset.ParseID(expectedIDs[k]) is.NoErr(err) bignum2 := big.Int(*id2) b = (&bignum2).Bytes() size := len(b) for size < 64 { b = append([]byte{0}, b...) size++ } for i, bb := range b { is.Equal(bb, byteData[k][i]) } } }
// Return the 64 raw bytes of a c4 id. I.e. the actual sha512. func (id *ID) RawBytes() (b []byte) { bignum := big.Int(*id) b_raw := (&bignum).Bytes() bytes64 := make([]byte, 64) padding := 64 - len(b_raw) // Can't use copy! // It doesn't properly handle leading zeros // copy(bytes64, b_raw) for i, bb := range b_raw { bytes64[padding+i] = bb } return bytes64[:] }
// ipv6AddrInit is called once at init() func ipv6AddrInit() { // Sorted for human readability ipv6AddrAttrs = []AttrName{ "size", // Same position as in IPv6 for output consistency "uint128", } ipv6AddrAttrMap = map[AttrName]func(ipv6 IPv6Addr) string{ "size": func(ipv6 IPv6Addr) string { netSize := big.NewInt(1) netSize = netSize.Lsh(netSize, uint(IPv6len*8-ipv6.Maskbits())) return netSize.Text(10) }, "uint128": func(ipv6 IPv6Addr) string { b := big.Int(*ipv6.Address) return b.Text(10) }, } }
// Bytes encodes the written bytes to C4 ID format. func (id *ID) Bytes() []byte { var bigNum big.Int bigID := big.Int(*id) bigNum.Set(&bigID) bigBase := big.NewInt(base) bigZero := big.NewInt(0) bigMod := new(big.Int) var encoded []byte for bigNum.Cmp(bigZero) > 0 { bigNum.DivMod(&bigNum, bigBase, bigMod) encoded = append([]byte{charset[bigMod.Int64()]}, encoded...) } // padding diff := idlen - 2 - len(encoded) encoded = append(bytes.Repeat(lowbyte, diff), encoded...) // c4... prefix encoded = append(prefix, encoded...) return encoded }
func TestAllFFFF(t *testing.T) { is := is.New(t) var b []byte for i := 0; i < 64; i++ { b = append(b, 0xFF) } bignum := big.NewInt(0) bignum = bignum.SetBytes(b) id := asset.ID(*bignum) is.Equal(id.String(), `c467RPWkcUr5dga8jgywjSup7CMoA9FNqkNjEFgAkEpF9vNktFnx77e2Js11EDL3BNu9MaKFUbacZRt1HYym4b8RNp`) id2, err := asset.ParseID(`c467RPWkcUr5dga8jgywjSup7CMoA9FNqkNjEFgAkEpF9vNktFnx77e2Js11EDL3BNu9MaKFUbacZRt1HYym4b8RNp`) is.NoErr(err) bignum2 := big.Int(*id2) b = (&bignum2).Bytes() for _, bb := range b { is.Equal(bb, 0xFF) } }
func TestAll0000(t *testing.T) { is := is.New(t) var b []byte for i := 0; i < 64; i++ { b = append(b, 0x00) } bignum := big.NewInt(0) bignum = bignum.SetBytes(b) id := asset.ID(*bignum) is.Equal(id.String(), `c41111111111111111111111111111111111111111111111111111111111111111111111111111111111111111`) id2, err := asset.ParseID(`c41111111111111111111111111111111111111111111111111111111111111111111111111111111111111111`) is.NoErr(err) bignum2 := big.Int(*id2) b = (&bignum2).Bytes() // This loop is unnecessary, bignum zero has only 1 byte. for _, bb := range b { is.Equal(bb, 0x00) } }
// NetIPMask create a new net.IPMask from the IPv6Addr. func (ipv6 IPv6Addr) NetIPMask() *net.IPMask { ipv6Mask := make(net.IPMask, IPv6len) m := big.Int(*ipv6.Mask) copy(ipv6Mask, m.Bytes()) return &ipv6Mask }
// AddressHexString returns a string with the IPv6Addr address represented as // a sequence of hex characters. This method is useful for debugging or by // operators who want to inspect an address. func (ipv6 IPv6Addr) AddressHexString() string { bi := big.Int(*ipv6.Address) return fmt.Sprintf("%032s", bi.Text(16)) }
// AddressBinString returns a string with the IPv6Addr's Address represented // as a sequence of '0' and '1' characters. This method is useful for // debugging or by operators who want to inspect an address. func (ipv6 IPv6Addr) AddressBinString() string { bi := big.Int(*ipv6.Address) return fmt.Sprintf("%0128s", bi.Text(2)) }