Let Multiaddr implement marshalers: binary, text, json
This commit is contained in:
parent
0297994296
commit
0aa80854ab
51
component.go
51
component.go
|
@ -3,6 +3,7 @@ package multiaddr
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -18,6 +19,54 @@ func (c *Component) Bytes() []byte {
|
||||||
return c.bytes
|
return c.bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Component) MarshalBinary() ([]byte, error) {
|
||||||
|
return c.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Component) UnmarshalBinary(data []byte) error {
|
||||||
|
_, comp, err := readComponent(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*c = comp
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Component) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(c.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Component) UnmarshalText(data []byte) error {
|
||||||
|
bytes, err := stringToBytes(string(data))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, comp, err := readComponent(bytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*c = comp
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Component) MarshalJSON() ([]byte, error) {
|
||||||
|
txt, err := c.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(string(txt))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Component) UnmarshalJSON(data []byte) error {
|
||||||
|
var v string
|
||||||
|
if err := json.Unmarshal(data, &v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.UnmarshalText([]byte(v))
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Component) Equal(o Multiaddr) bool {
|
func (c *Component) Equal(o Multiaddr) bool {
|
||||||
return bytes.Equal(c.bytes, o.Bytes())
|
return bytes.Equal(c.bytes, o.Bytes())
|
||||||
}
|
}
|
||||||
|
@ -34,7 +83,7 @@ func (c *Component) Decapsulate(o Multiaddr) Multiaddr {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Component) Encapsulate(o Multiaddr) Multiaddr {
|
func (c *Component) Encapsulate(o Multiaddr) Multiaddr {
|
||||||
m := multiaddr{bytes: c.bytes}
|
m := &multiaddr{bytes: c.bytes}
|
||||||
return m.Encapsulate(o)
|
return m.Encapsulate(o)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
interface.go
12
interface.go
|
@ -1,5 +1,10 @@
|
||||||
package multiaddr
|
package multiaddr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Multiaddr is a cross-protocol, cross-platform format for representing
|
Multiaddr is a cross-protocol, cross-platform format for representing
|
||||||
internet addresses. It emphasizes explicitness and self-description.
|
internet addresses. It emphasizes explicitness and self-description.
|
||||||
|
@ -14,6 +19,13 @@ Multiaddrs have both a binary and string representation.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
type Multiaddr interface {
|
type Multiaddr interface {
|
||||||
|
json.Marshaler
|
||||||
|
json.Unmarshaler
|
||||||
|
encoding.TextMarshaler
|
||||||
|
encoding.TextUnmarshaler
|
||||||
|
encoding.BinaryMarshaler
|
||||||
|
encoding.BinaryUnmarshaler
|
||||||
|
|
||||||
// Equal returns whether two Multiaddrs are exactly equal
|
// Equal returns whether two Multiaddrs are exactly equal
|
||||||
Equal(Multiaddr) bool
|
Equal(Multiaddr) bool
|
||||||
|
|
||||||
|
|
63
multiaddr.go
63
multiaddr.go
|
@ -2,6 +2,7 @@ package multiaddr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -24,7 +25,7 @@ func NewMultiaddr(s string) (a Multiaddr, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return multiaddr{bytes: b}, nil
|
return &multiaddr{bytes: b}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMultiaddrBytes initializes a Multiaddr from a byte representation.
|
// NewMultiaddrBytes initializes a Multiaddr from a byte representation.
|
||||||
|
@ -41,23 +42,23 @@ func NewMultiaddrBytes(b []byte) (a Multiaddr, err error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return multiaddr{bytes: b}, nil
|
return &multiaddr{bytes: b}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal tests whether two multiaddrs are equal
|
// Equal tests whether two multiaddrs are equal
|
||||||
func (m multiaddr) Equal(m2 Multiaddr) bool {
|
func (m *multiaddr) Equal(m2 Multiaddr) bool {
|
||||||
return bytes.Equal(m.bytes, m2.Bytes())
|
return bytes.Equal(m.bytes, m2.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes returns the []byte representation of this Multiaddr
|
// Bytes returns the []byte representation of this Multiaddr
|
||||||
//
|
//
|
||||||
// Do not modify the returned buffer, it may be shared.
|
// Do not modify the returned buffer, it may be shared.
|
||||||
func (m multiaddr) Bytes() []byte {
|
func (m *multiaddr) Bytes() []byte {
|
||||||
return m.bytes
|
return m.bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the string representation of a Multiaddr
|
// String returns the string representation of a Multiaddr
|
||||||
func (m multiaddr) String() string {
|
func (m *multiaddr) String() string {
|
||||||
s, err := bytesToString(m.bytes)
|
s, err := bytesToString(m.bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("multiaddr failed to convert back to string. corrupted? %s", err))
|
panic(fmt.Errorf("multiaddr failed to convert back to string. corrupted? %s", err))
|
||||||
|
@ -65,9 +66,49 @@ func (m multiaddr) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *multiaddr) MarshalBinary() ([]byte, error) {
|
||||||
|
return m.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiaddr) UnmarshalBinary(data []byte) error {
|
||||||
|
new, err := NewMultiaddrBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*m = *(new.(*multiaddr))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiaddr) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(m.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiaddr) UnmarshalText(data []byte) error {
|
||||||
|
new, err := NewMultiaddr(string(data))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*m = *(new.(*multiaddr))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiaddr) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(m.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multiaddr) UnmarshalJSON(data []byte) error {
|
||||||
|
var v string
|
||||||
|
if err := json.Unmarshal(data, &v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
new, err := NewMultiaddr(v)
|
||||||
|
*m = *(new.(*multiaddr))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Protocols returns the list of protocols this Multiaddr has.
|
// Protocols returns the list of protocols this Multiaddr has.
|
||||||
// will panic in case we access bytes incorrectly.
|
// will panic in case we access bytes incorrectly.
|
||||||
func (m multiaddr) Protocols() []Protocol {
|
func (m *multiaddr) Protocols() []Protocol {
|
||||||
ps := make([]Protocol, 0, 8)
|
ps := make([]Protocol, 0, 8)
|
||||||
b := m.bytes
|
b := m.bytes
|
||||||
for len(b) > 0 {
|
for len(b) > 0 {
|
||||||
|
@ -96,18 +137,18 @@ func (m multiaddr) Protocols() []Protocol {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encapsulate wraps a given Multiaddr, returning the resulting joined Multiaddr
|
// Encapsulate wraps a given Multiaddr, returning the resulting joined Multiaddr
|
||||||
func (m multiaddr) Encapsulate(o Multiaddr) Multiaddr {
|
func (m *multiaddr) Encapsulate(o Multiaddr) Multiaddr {
|
||||||
mb := m.bytes
|
mb := m.bytes
|
||||||
ob := o.Bytes()
|
ob := o.Bytes()
|
||||||
|
|
||||||
b := make([]byte, len(mb)+len(ob))
|
b := make([]byte, len(mb)+len(ob))
|
||||||
copy(b, mb)
|
copy(b, mb)
|
||||||
copy(b[len(mb):], ob)
|
copy(b[len(mb):], ob)
|
||||||
return multiaddr{bytes: b}
|
return &multiaddr{bytes: b}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decapsulate unwraps Multiaddr up until the given Multiaddr is found.
|
// Decapsulate unwraps Multiaddr up until the given Multiaddr is found.
|
||||||
func (m multiaddr) Decapsulate(o Multiaddr) Multiaddr {
|
func (m *multiaddr) Decapsulate(o Multiaddr) Multiaddr {
|
||||||
s1 := m.String()
|
s1 := m.String()
|
||||||
s2 := o.String()
|
s2 := o.String()
|
||||||
i := strings.LastIndex(s1, s2)
|
i := strings.LastIndex(s1, s2)
|
||||||
|
@ -115,7 +156,7 @@ func (m multiaddr) Decapsulate(o Multiaddr) Multiaddr {
|
||||||
// if multiaddr not contained, returns a copy.
|
// if multiaddr not contained, returns a copy.
|
||||||
cpy := make([]byte, len(m.bytes))
|
cpy := make([]byte, len(m.bytes))
|
||||||
copy(cpy, m.bytes)
|
copy(cpy, m.bytes)
|
||||||
return multiaddr{bytes: cpy}
|
return &multiaddr{bytes: cpy}
|
||||||
}
|
}
|
||||||
|
|
||||||
ma, err := NewMultiaddr(s1[:i])
|
ma, err := NewMultiaddr(s1[:i])
|
||||||
|
@ -127,7 +168,7 @@ func (m multiaddr) Decapsulate(o Multiaddr) Multiaddr {
|
||||||
|
|
||||||
var ErrProtocolNotFound = fmt.Errorf("protocol not found in multiaddr")
|
var ErrProtocolNotFound = fmt.Errorf("protocol not found in multiaddr")
|
||||||
|
|
||||||
func (m multiaddr) ValueForProtocol(code int) (value string, err error) {
|
func (m *multiaddr) ValueForProtocol(code int) (value string, err error) {
|
||||||
err = ErrProtocolNotFound
|
err = ErrProtocolNotFound
|
||||||
ForEach(m, func(c Component) bool {
|
ForEach(m, func(c Component) bool {
|
||||||
if c.Protocol().Code == code {
|
if c.Protocol().Code == code {
|
||||||
|
|
|
@ -555,3 +555,108 @@ func TestZone(t *testing.T) {
|
||||||
t.Errorf("expected %s, got %s", ip6String, ma2.String())
|
t.Errorf("expected %s, got %s", ip6String, ma2.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBinaryMarshaler(t *testing.T) {
|
||||||
|
addr := newMultiaddr(t, "/ip4/0.0.0.0/tcp/4001")
|
||||||
|
b, err := addr.MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
addr2 := newMultiaddr(t, "")
|
||||||
|
if err = addr2.UnmarshalBinary(b); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !addr.Equal(addr2) {
|
||||||
|
t.Error("expected equal addresses in circular marshaling test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTextMarshaler(t *testing.T) {
|
||||||
|
addr := newMultiaddr(t, "/ip4/0.0.0.0/tcp/4001")
|
||||||
|
b, err := addr.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
addr2 := newMultiaddr(t, "")
|
||||||
|
if err = addr2.UnmarshalText(b); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !addr.Equal(addr2) {
|
||||||
|
t.Error("expected equal addresses in circular marshaling test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONMarshaler(t *testing.T) {
|
||||||
|
addr := newMultiaddr(t, "/ip4/0.0.0.0/tcp/4001")
|
||||||
|
b, err := addr.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
addr2 := newMultiaddr(t, "")
|
||||||
|
if err = addr2.UnmarshalJSON(b); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !addr.Equal(addr2) {
|
||||||
|
t.Error("expected equal addresses in circular marshaling test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComponentBinaryMarshaler(t *testing.T) {
|
||||||
|
comp, err := NewComponent("ip4", "0.0.0.0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
b, err := comp.MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
comp2 := &Component{}
|
||||||
|
if err = comp2.UnmarshalBinary(b); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !comp.Equal(comp2) {
|
||||||
|
t.Error("expected equal components in circular marshaling test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComponentTextMarshaler(t *testing.T) {
|
||||||
|
comp, err := NewComponent("ip4", "0.0.0.0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
b, err := comp.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
comp2 := &Component{}
|
||||||
|
if err = comp2.UnmarshalText(b); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !comp.Equal(comp2) {
|
||||||
|
t.Error("expected equal components in circular marshaling test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComponentJSONMarshaler(t *testing.T) {
|
||||||
|
comp, err := NewComponent("ip4", "0.0.0.0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
b, err := comp.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
comp2 := &Component{}
|
||||||
|
if err = comp2.UnmarshalJSON(b); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !comp.Equal(comp2) {
|
||||||
|
t.Error("expected equal components in circular marshaling test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
10
util.go
10
util.go
|
@ -21,7 +21,7 @@ func Join(ms ...Multiaddr) Multiaddr {
|
||||||
case 0:
|
case 0:
|
||||||
// empty multiaddr, unfortunately, we have callers that rely on
|
// empty multiaddr, unfortunately, we have callers that rely on
|
||||||
// this contract.
|
// this contract.
|
||||||
return multiaddr{}
|
return &multiaddr{}
|
||||||
case 1:
|
case 1:
|
||||||
return ms[0]
|
return ms[0]
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ func Join(ms ...Multiaddr) Multiaddr {
|
||||||
for _, mb := range bs {
|
for _, mb := range bs {
|
||||||
bidx += copy(b[bidx:], mb)
|
bidx += copy(b[bidx:], mb)
|
||||||
}
|
}
|
||||||
return multiaddr{bytes: b}
|
return &multiaddr{bytes: b}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cast re-casts a byte slice as a multiaddr. will panic if it fails to parse.
|
// Cast re-casts a byte slice as a multiaddr. will panic if it fails to parse.
|
||||||
|
@ -77,7 +77,7 @@ func SplitFirst(m Multiaddr) (*Component, Multiaddr) {
|
||||||
if len(b) == n {
|
if len(b) == n {
|
||||||
return &c, nil
|
return &c, nil
|
||||||
}
|
}
|
||||||
return &c, multiaddr{b[n:]}
|
return &c, &multiaddr{b[n:]}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SplitLast returns the rest of the multiaddr and the last component.
|
// SplitLast returns the rest of the multiaddr and the last component.
|
||||||
|
@ -109,7 +109,7 @@ func SplitLast(m Multiaddr) (Multiaddr, *Component) {
|
||||||
// Only one component
|
// Only one component
|
||||||
return nil, &c
|
return nil, &c
|
||||||
}
|
}
|
||||||
return multiaddr{b[:offset]}, &c
|
return &multiaddr{b[:offset]}, &c
|
||||||
}
|
}
|
||||||
offset += n
|
offset += n
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ func SplitFunc(m Multiaddr, cb func(Component) bool) (Multiaddr, Multiaddr) {
|
||||||
case len(b):
|
case len(b):
|
||||||
return m, nil
|
return m, nil
|
||||||
default:
|
default:
|
||||||
return multiaddr{b[:offset]}, multiaddr{b[offset:]}
|
return &multiaddr{b[:offset]}, &multiaddr{b[offset:]}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue