Skip to content

Commit 9943117

Browse files
authored
Merge pull request #95 from multiformats/marshalers
Let Multiaddr implement marshalers: binary, text, json
2 parents 06f7d80 + 21e6525 commit 9943117

File tree

7 files changed

+226
-19
lines changed

7 files changed

+226
-19
lines changed

.gx/lastpubver

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.4.0: QmNTCey11oxhb1AxDnQBRHtdhap6Ctud872NjAYPYYXPuc
1+
1.4.1: QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL

component.go

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package multiaddr
33
import (
44
"bytes"
55
"encoding/binary"
6+
"encoding/json"
67
"fmt"
78
"strings"
89
)
@@ -18,6 +19,54 @@ func (c *Component) Bytes() []byte {
1819
return c.bytes
1920
}
2021

22+
func (c *Component) MarshalBinary() ([]byte, error) {
23+
return c.Bytes(), nil
24+
}
25+
26+
func (c *Component) UnmarshalBinary(data []byte) error {
27+
_, comp, err := readComponent(data)
28+
if err != nil {
29+
return err
30+
}
31+
*c = comp
32+
return nil
33+
}
34+
35+
func (c *Component) MarshalText() ([]byte, error) {
36+
return []byte(c.String()), nil
37+
}
38+
39+
func (c *Component) UnmarshalText(data []byte) error {
40+
bytes, err := stringToBytes(string(data))
41+
if err != nil {
42+
return err
43+
}
44+
_, comp, err := readComponent(bytes)
45+
if err != nil {
46+
return err
47+
}
48+
*c = comp
49+
return nil
50+
}
51+
52+
func (c *Component) MarshalJSON() ([]byte, error) {
53+
txt, err := c.MarshalText()
54+
if err != nil {
55+
return nil, err
56+
}
57+
58+
return json.Marshal(string(txt))
59+
}
60+
61+
func (m *Component) UnmarshalJSON(data []byte) error {
62+
var v string
63+
if err := json.Unmarshal(data, &v); err != nil {
64+
return err
65+
}
66+
67+
return m.UnmarshalText([]byte(v))
68+
}
69+
2170
func (c *Component) Equal(o Multiaddr) bool {
2271
return bytes.Equal(c.bytes, o.Bytes())
2372
}
@@ -34,7 +83,7 @@ func (c *Component) Decapsulate(o Multiaddr) Multiaddr {
3483
}
3584

3685
func (c *Component) Encapsulate(o Multiaddr) Multiaddr {
37-
m := multiaddr{bytes: c.bytes}
86+
m := &multiaddr{bytes: c.bytes}
3887
return m.Encapsulate(o)
3988
}
4089

interface.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package multiaddr
22

3+
import (
4+
"encoding"
5+
"encoding/json"
6+
)
7+
38
/*
49
Multiaddr is a cross-protocol, cross-platform format for representing
510
internet addresses. It emphasizes explicitness and self-description.
@@ -14,6 +19,13 @@ Multiaddrs have both a binary and string representation.
1419
1520
*/
1621
type Multiaddr interface {
22+
json.Marshaler
23+
json.Unmarshaler
24+
encoding.TextMarshaler
25+
encoding.TextUnmarshaler
26+
encoding.BinaryMarshaler
27+
encoding.BinaryUnmarshaler
28+
1729
// Equal returns whether two Multiaddrs are exactly equal
1830
Equal(Multiaddr) bool
1931

multiaddr.go

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package multiaddr
22

33
import (
44
"bytes"
5+
"encoding/json"
56
"fmt"
67
"log"
78
"strings"
@@ -24,7 +25,7 @@ func NewMultiaddr(s string) (a Multiaddr, err error) {
2425
if err != nil {
2526
return nil, err
2627
}
27-
return multiaddr{bytes: b}, nil
28+
return &multiaddr{bytes: b}, nil
2829
}
2930

3031
// NewMultiaddrBytes initializes a Multiaddr from a byte representation.
@@ -41,33 +42,73 @@ func NewMultiaddrBytes(b []byte) (a Multiaddr, err error) {
4142
return nil, err
4243
}
4344

44-
return multiaddr{bytes: b}, nil
45+
return &multiaddr{bytes: b}, nil
4546
}
4647

4748
// Equal tests whether two multiaddrs are equal
48-
func (m multiaddr) Equal(m2 Multiaddr) bool {
49+
func (m *multiaddr) Equal(m2 Multiaddr) bool {
4950
return bytes.Equal(m.bytes, m2.Bytes())
5051
}
5152

5253
// Bytes returns the []byte representation of this Multiaddr
5354
//
5455
// Do not modify the returned buffer, it may be shared.
55-
func (m multiaddr) Bytes() []byte {
56+
func (m *multiaddr) Bytes() []byte {
5657
return m.bytes
5758
}
5859

5960
// String returns the string representation of a Multiaddr
60-
func (m multiaddr) String() string {
61+
func (m *multiaddr) String() string {
6162
s, err := bytesToString(m.bytes)
6263
if err != nil {
6364
panic(fmt.Errorf("multiaddr failed to convert back to string. corrupted? %s", err))
6465
}
6566
return s
6667
}
6768

69+
func (m *multiaddr) MarshalBinary() ([]byte, error) {
70+
return m.Bytes(), nil
71+
}
72+
73+
func (m *multiaddr) UnmarshalBinary(data []byte) error {
74+
new, err := NewMultiaddrBytes(data)
75+
if err != nil {
76+
return err
77+
}
78+
*m = *(new.(*multiaddr))
79+
return nil
80+
}
81+
82+
func (m *multiaddr) MarshalText() ([]byte, error) {
83+
return []byte(m.String()), nil
84+
}
85+
86+
func (m *multiaddr) UnmarshalText(data []byte) error {
87+
new, err := NewMultiaddr(string(data))
88+
if err != nil {
89+
return err
90+
}
91+
*m = *(new.(*multiaddr))
92+
return nil
93+
}
94+
95+
func (m *multiaddr) MarshalJSON() ([]byte, error) {
96+
return json.Marshal(m.String())
97+
}
98+
99+
func (m *multiaddr) UnmarshalJSON(data []byte) error {
100+
var v string
101+
if err := json.Unmarshal(data, &v); err != nil {
102+
return err
103+
}
104+
new, err := NewMultiaddr(v)
105+
*m = *(new.(*multiaddr))
106+
return err
107+
}
108+
68109
// Protocols returns the list of protocols this Multiaddr has.
69110
// will panic in case we access bytes incorrectly.
70-
func (m multiaddr) Protocols() []Protocol {
111+
func (m *multiaddr) Protocols() []Protocol {
71112
ps := make([]Protocol, 0, 8)
72113
b := m.bytes
73114
for len(b) > 0 {
@@ -96,26 +137,26 @@ func (m multiaddr) Protocols() []Protocol {
96137
}
97138

98139
// Encapsulate wraps a given Multiaddr, returning the resulting joined Multiaddr
99-
func (m multiaddr) Encapsulate(o Multiaddr) Multiaddr {
140+
func (m *multiaddr) Encapsulate(o Multiaddr) Multiaddr {
100141
mb := m.bytes
101142
ob := o.Bytes()
102143

103144
b := make([]byte, len(mb)+len(ob))
104145
copy(b, mb)
105146
copy(b[len(mb):], ob)
106-
return multiaddr{bytes: b}
147+
return &multiaddr{bytes: b}
107148
}
108149

109150
// Decapsulate unwraps Multiaddr up until the given Multiaddr is found.
110-
func (m multiaddr) Decapsulate(o Multiaddr) Multiaddr {
151+
func (m *multiaddr) Decapsulate(o Multiaddr) Multiaddr {
111152
s1 := m.String()
112153
s2 := o.String()
113154
i := strings.LastIndex(s1, s2)
114155
if i < 0 {
115156
// if multiaddr not contained, returns a copy.
116157
cpy := make([]byte, len(m.bytes))
117158
copy(cpy, m.bytes)
118-
return multiaddr{bytes: cpy}
159+
return &multiaddr{bytes: cpy}
119160
}
120161

121162
ma, err := NewMultiaddr(s1[:i])
@@ -127,7 +168,7 @@ func (m multiaddr) Decapsulate(o Multiaddr) Multiaddr {
127168

128169
var ErrProtocolNotFound = fmt.Errorf("protocol not found in multiaddr")
129170

130-
func (m multiaddr) ValueForProtocol(code int) (value string, err error) {
171+
func (m *multiaddr) ValueForProtocol(code int) (value string, err error) {
131172
err = ErrProtocolNotFound
132173
ForEach(m, func(c Component) bool {
133174
if c.Protocol().Code == code {

multiaddr_test.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,3 +555,108 @@ func TestZone(t *testing.T) {
555555
t.Errorf("expected %s, got %s", ip6String, ma2.String())
556556
}
557557
}
558+
559+
func TestBinaryMarshaler(t *testing.T) {
560+
addr := newMultiaddr(t, "/ip4/0.0.0.0/tcp/4001")
561+
b, err := addr.MarshalBinary()
562+
if err != nil {
563+
t.Fatal(err)
564+
}
565+
566+
addr2 := newMultiaddr(t, "")
567+
if err = addr2.UnmarshalBinary(b); err != nil {
568+
t.Fatal(err)
569+
}
570+
if !addr.Equal(addr2) {
571+
t.Error("expected equal addresses in circular marshaling test")
572+
}
573+
}
574+
575+
func TestTextMarshaler(t *testing.T) {
576+
addr := newMultiaddr(t, "/ip4/0.0.0.0/tcp/4001")
577+
b, err := addr.MarshalText()
578+
if err != nil {
579+
t.Fatal(err)
580+
}
581+
582+
addr2 := newMultiaddr(t, "")
583+
if err = addr2.UnmarshalText(b); err != nil {
584+
t.Fatal(err)
585+
}
586+
if !addr.Equal(addr2) {
587+
t.Error("expected equal addresses in circular marshaling test")
588+
}
589+
}
590+
591+
func TestJSONMarshaler(t *testing.T) {
592+
addr := newMultiaddr(t, "/ip4/0.0.0.0/tcp/4001")
593+
b, err := addr.MarshalJSON()
594+
if err != nil {
595+
t.Fatal(err)
596+
}
597+
598+
addr2 := newMultiaddr(t, "")
599+
if err = addr2.UnmarshalJSON(b); err != nil {
600+
t.Fatal(err)
601+
}
602+
if !addr.Equal(addr2) {
603+
t.Error("expected equal addresses in circular marshaling test")
604+
}
605+
}
606+
607+
func TestComponentBinaryMarshaler(t *testing.T) {
608+
comp, err := NewComponent("ip4", "0.0.0.0")
609+
if err != nil {
610+
t.Fatal(err)
611+
}
612+
b, err := comp.MarshalBinary()
613+
if err != nil {
614+
t.Fatal(err)
615+
}
616+
617+
comp2 := &Component{}
618+
if err = comp2.UnmarshalBinary(b); err != nil {
619+
t.Fatal(err)
620+
}
621+
if !comp.Equal(comp2) {
622+
t.Error("expected equal components in circular marshaling test")
623+
}
624+
}
625+
626+
func TestComponentTextMarshaler(t *testing.T) {
627+
comp, err := NewComponent("ip4", "0.0.0.0")
628+
if err != nil {
629+
t.Fatal(err)
630+
}
631+
b, err := comp.MarshalText()
632+
if err != nil {
633+
t.Fatal(err)
634+
}
635+
636+
comp2 := &Component{}
637+
if err = comp2.UnmarshalText(b); err != nil {
638+
t.Fatal(err)
639+
}
640+
if !comp.Equal(comp2) {
641+
t.Error("expected equal components in circular marshaling test")
642+
}
643+
}
644+
645+
func TestComponentJSONMarshaler(t *testing.T) {
646+
comp, err := NewComponent("ip4", "0.0.0.0")
647+
if err != nil {
648+
t.Fatal(err)
649+
}
650+
b, err := comp.MarshalJSON()
651+
if err != nil {
652+
t.Fatal(err)
653+
}
654+
655+
comp2 := &Component{}
656+
if err = comp2.UnmarshalJSON(b); err != nil {
657+
t.Fatal(err)
658+
}
659+
if !comp.Equal(comp2) {
660+
t.Error("expected equal components in circular marshaling test")
661+
}
662+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@
1818
"license": "MIT",
1919
"name": "go-multiaddr",
2020
"releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
21-
"version": "1.4.0"
21+
"version": "1.4.1"
2222
}
2323

util.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func Join(ms ...Multiaddr) Multiaddr {
2121
case 0:
2222
// empty multiaddr, unfortunately, we have callers that rely on
2323
// this contract.
24-
return multiaddr{}
24+
return &multiaddr{}
2525
case 1:
2626
return ms[0]
2727
}
@@ -38,7 +38,7 @@ func Join(ms ...Multiaddr) Multiaddr {
3838
for _, mb := range bs {
3939
bidx += copy(b[bidx:], mb)
4040
}
41-
return multiaddr{bytes: b}
41+
return &multiaddr{bytes: b}
4242
}
4343

4444
// 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) {
7777
if len(b) == n {
7878
return &c, nil
7979
}
80-
return &c, multiaddr{b[n:]}
80+
return &c, &multiaddr{b[n:]}
8181
}
8282

8383
// SplitLast returns the rest of the multiaddr and the last component.
@@ -109,7 +109,7 @@ func SplitLast(m Multiaddr) (Multiaddr, *Component) {
109109
// Only one component
110110
return nil, &c
111111
}
112-
return multiaddr{b[:offset]}, &c
112+
return &multiaddr{b[:offset]}, &c
113113
}
114114
offset += n
115115
}
@@ -152,7 +152,7 @@ func SplitFunc(m Multiaddr, cb func(Component) bool) (Multiaddr, Multiaddr) {
152152
case len(b):
153153
return m, nil
154154
default:
155-
return multiaddr{b[:offset]}, multiaddr{b[offset:]}
155+
return &multiaddr{b[:offset]}, &multiaddr{b[offset:]}
156156
}
157157
}
158158

0 commit comments

Comments
 (0)