Skip to content

Commit 3fbfcdd

Browse files
committed
Use nil as zero value for Multiaddr
1 parent f85c4f0 commit 3fbfcdd

File tree

7 files changed

+111
-26
lines changed

7 files changed

+111
-26
lines changed

Diff for: codec.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func readComponent(b []byte) (int, Component, error) {
119119

120120
func readMultiaddr(b []byte) (int, Multiaddr, error) {
121121
if len(b) == 0 {
122-
return 0, Multiaddr{}, fmt.Errorf("empty multiaddr")
122+
return 0, nil, fmt.Errorf("empty multiaddr")
123123
}
124124

125125
var res Multiaddr
@@ -128,14 +128,14 @@ func readMultiaddr(b []byte) (int, Multiaddr, error) {
128128
for len(b) > 0 {
129129
n, c, err := readComponent(b)
130130
if err != nil {
131-
return 0, Multiaddr{}, err
131+
return 0, nil, err
132132
}
133133
b = b[n:]
134134
bytesRead += n
135135

136136
if sawPathComponent {
137137
// It is an error to have another component after a path component.
138-
return bytesRead, Multiaddr{}, fmt.Errorf("unexpected component after path component")
138+
return bytesRead, nil, fmt.Errorf("unexpected component after path component")
139139
}
140140
sawPathComponent = c.protocol.Path
141141
res = append(res, c)

Diff for: component.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ type Component struct {
1717
}
1818

1919
func (c Component) AsMultiaddr() Multiaddr {
20+
if c.Empty() {
21+
return nil
22+
}
2023
return []Component{c}
2124
}
2225

@@ -127,6 +130,9 @@ func (c Component) RawValue() []byte {
127130
}
128131

129132
func (c Component) Value() string {
133+
if c.Empty() {
134+
return ""
135+
}
130136
// This Component MUST have been checked by validateComponent when created
131137
value, _ := c.valueAndErr()
132138
return value
@@ -180,7 +186,6 @@ func NewComponent(protocol, value string) (Component, error) {
180186
return Component{}, fmt.Errorf("protocol %s doesn't take a value", p.Name)
181187
}
182188
return newComponent(p, nil)
183-
// TODO: handle path /?
184189
}
185190

186191
func newComponent(protocol Protocol, bvalue []byte) (Component, error) {

Diff for: multiaddr.go

+17-4
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func NewMultiaddr(s string) (a Multiaddr, err error) {
3737
}()
3838
b, err := stringToBytes(s)
3939
if err != nil {
40-
return Multiaddr{}, err
40+
return nil, err
4141
}
4242
return NewMultiaddrBytes(b)
4343
}
@@ -53,7 +53,10 @@ func NewMultiaddrBytes(b []byte) (a Multiaddr, err error) {
5353
}()
5454
bytesRead, m, err := readMultiaddr(b)
5555
if bytesRead != len(b) {
56-
return Multiaddr{}, fmt.Errorf("Unexpected extra data. %v bytes leftover", len(b)-bytesRead)
56+
return nil, fmt.Errorf("Unexpected extra data. %v bytes leftover", len(b)-bytesRead)
57+
}
58+
if len(m) == 0 {
59+
return nil, err
5760
}
5861
return m, err
5962
}
@@ -175,6 +178,16 @@ func (m Multiaddr) Encapsulate(o Multiaddr) Multiaddr {
175178
return Join(m, o)
176179
}
177180

181+
func (m Multiaddr) EncapsulateC(c Component) Multiaddr {
182+
if c.Empty() {
183+
return m
184+
}
185+
out := make([]Component, 0, len(m)+1)
186+
out = append(out, m...)
187+
out = append(out, c)
188+
return out
189+
}
190+
178191
// Decapsulate unwraps Multiaddr up until the given Multiaddr is found.
179192
func (m Multiaddr) Decapsulate(rightParts Multiaddr) Multiaddr {
180193
leftParts := m
@@ -200,7 +213,7 @@ func (m Multiaddr) Decapsulate(rightParts Multiaddr) Multiaddr {
200213
}
201214

202215
if lastIndex == 0 {
203-
return Multiaddr{}
216+
return nil
204217
}
205218

206219
if lastIndex < 0 {
@@ -262,7 +275,7 @@ func Unique(addrs []Multiaddr) []Multiaddr {
262275
}
263276
}
264277
for i := idx; i < len(addrs); i++ {
265-
addrs[i] = Multiaddr{}
278+
addrs[i] = nil
266279
}
267280
return addrs[:idx]
268281
}

Diff for: multiaddr_test.go

+50-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,53 @@ func newMultiaddr(t *testing.T, a string) Multiaddr {
2121
return m
2222
}
2323

24+
func TestReturnsNilOnEmpty(t *testing.T) {
25+
a := StringCast("/ip4/1.2.3.4")
26+
a, _ = SplitLast(a)
27+
require.Nil(t, a)
28+
a, _ = SplitLast(a)
29+
require.Nil(t, a)
30+
31+
// Test that empty multiaddr from various operations returns nil
32+
a = StringCast("/ip4/1.2.3.4/tcp/1234")
33+
_, a = SplitFirst(a)
34+
_, a = SplitFirst(a)
35+
require.Nil(t, a)
36+
_, a = SplitFirst(a)
37+
require.Nil(t, a)
38+
39+
a = StringCast("/ip4/1.2.3.4/tcp/1234")
40+
a = a.Decapsulate(a)
41+
require.Nil(t, a)
42+
43+
a = StringCast("/ip4/1.2.3.4/tcp/1234")
44+
a = a.Decapsulate(StringCast("/tcp/1234"))
45+
a = a.Decapsulate(StringCast("/ip4/1.2.3.4"))
46+
require.Nil(t, a)
47+
48+
// Test that SplitFunc returns nil when we split at beginning and end
49+
a = StringCast("/ip4/1.2.3.4/tcp/1234")
50+
pre, _ := SplitFunc(a, func(c Component) bool {
51+
return c.Protocol().Code == P_IP4
52+
})
53+
require.Nil(t, pre)
54+
55+
a = StringCast("/ip4/1.2.3.4/tcp/1234")
56+
_, post := SplitFunc(a, func(c Component) bool {
57+
return false
58+
})
59+
require.Nil(t, post)
60+
61+
_, err := NewMultiaddr("")
62+
require.Error(t, err)
63+
64+
a = JoinComponents()
65+
require.Nil(t, a)
66+
67+
a = Join()
68+
require.Nil(t, a)
69+
}
70+
2471
func TestConstructFails(t *testing.T) {
2572
cases := []string{
2673
"/ip4",
@@ -459,7 +506,7 @@ func TestEncapsulate(t *testing.T) {
459506

460507
m4, _ := NewMultiaddr("/ip4/127.0.0.1")
461508
d := c.Decapsulate(m4)
462-
if !d.Empty() {
509+
if d != nil {
463510
t.Error("decapsulate /ip4 failed: ", d)
464511
}
465512
}
@@ -480,7 +527,7 @@ func TestDecapsulateComment(t *testing.T) {
480527

481528
m = StringCast("/ip4/1.2.3.4/tcp/80")
482529
rest = m.Decapsulate(StringCast("/ip4/1.2.3.4"))
483-
require.True(t, rest.Empty(), "expected a nil multiaddr if we decapsulate everything")
530+
require.Nil(t, rest, "expected a nil multiaddr if we decapsulate everything")
484531
}
485532

486533
func TestDecapsulate(t *testing.T) {
@@ -513,7 +560,7 @@ func TestDecapsulate(t *testing.T) {
513560
actualMa := left.Decapsulate(right)
514561

515562
if tc.expected == "" {
516-
require.True(t, actualMa.Empty(), "expected nil")
563+
require.Nil(t, actualMa, "expected nil")
517564
return
518565
}
519566

Diff for: net/convert.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func FromIPAndZone(ip net.IP, zone string) (ma.Multiaddr, error) {
106106
case ip.To4() != nil:
107107
c, err := ma.NewComponent("ip4", ip.String())
108108
if err != nil {
109-
return ma.Multiaddr{}, err
109+
return nil, err
110110
}
111111
return c.AsMultiaddr(), nil
112112
case ip.To16() != nil:

Diff for: util.go

+24-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ func Split(m Multiaddr) []Component {
1212
}
1313

1414
func JoinComponents(cs ...Component) Multiaddr {
15+
if len(cs) == 0 {
16+
return nil
17+
}
1518
out := make([]Component, 0, len(cs))
1619
for _, c := range cs {
1720
if !c.Empty() {
@@ -27,6 +30,9 @@ func Join(ms ...Multiaddr) Multiaddr {
2730
for _, m := range ms {
2831
size += len(m)
2932
}
33+
if size == 0 {
34+
return nil
35+
}
3036

3137
out := make([]Component, 0, size)
3238
for _, m := range ms {
@@ -60,15 +66,22 @@ func StringCast(s string) Multiaddr {
6066
// SplitFirst returns the first component and the rest of the multiaddr.
6167
func SplitFirst(m Multiaddr) (Component, Multiaddr) {
6268
if m.Empty() {
63-
return Component{}, Multiaddr{}
69+
return Component{}, nil
70+
}
71+
if len(m) == 1 {
72+
return m[0], nil
6473
}
6574
return m[0], m[1:]
6675
}
6776

6877
// SplitLast returns the rest of the multiaddr and the last component.
6978
func SplitLast(m Multiaddr) (Multiaddr, Component) {
7079
if m.Empty() {
71-
return Multiaddr{}, Component{}
80+
return nil, Component{}
81+
}
82+
if len(m) == 1 {
83+
// We want to explicitly return a nil slice if the prefix is now empty.
84+
return nil, m[0]
7285
}
7386
return m[:len(m)-1], m[len(m)-1]
7487
}
@@ -78,7 +91,7 @@ func SplitLast(m Multiaddr) (Multiaddr, Component) {
7891
// *second* multiaddr.
7992
func SplitFunc(m Multiaddr, cb func(Component) bool) (Multiaddr, Multiaddr) {
8093
if m.Empty() {
81-
return Multiaddr{}, Multiaddr{}
94+
return nil, nil
8295
}
8396

8497
idx := len(m)
@@ -88,7 +101,14 @@ func SplitFunc(m Multiaddr, cb func(Component) bool) (Multiaddr, Multiaddr) {
88101
break
89102
}
90103
}
91-
return m[:idx], m[idx:]
104+
pre, post := m[:idx], m[idx:]
105+
if pre.Empty() {
106+
pre = nil
107+
}
108+
if post.Empty() {
109+
post = nil
110+
}
111+
return pre, post
92112
}
93113

94114
// ForEach walks over the multiaddr, component by component.

Diff for: util_test.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@ func TestSplitFirstLast(t *testing.T) {
2222
rest, last := SplitLast(addr)
2323
if len(x) == 0 {
2424
if !head.Empty() {
25-
t.Error("expected head to be nil")
25+
t.Error("expected head to be empty")
2626
}
27-
if !tail.Empty() {
27+
if tail != nil {
2828
t.Error("expected tail to be nil")
2929
}
30-
if !rest.Empty() {
30+
if rest != nil {
3131
t.Error("expected rest to be nil")
3232
}
3333
if !last.Empty() {
34-
t.Error("expected last to be nil")
34+
t.Error("expected last to be empty")
3535
}
3636
continue
3737
}
@@ -42,10 +42,10 @@ func TestSplitFirstLast(t *testing.T) {
4242
t.Errorf("expected %s to be %s", head, x[len(x)-1])
4343
}
4444
if len(x) == 1 {
45-
if !tail.Empty() {
45+
if tail != nil {
4646
t.Error("expected tail to be nil")
4747
}
48-
if !rest.Empty() {
48+
if rest != nil {
4949
t.Error("expected rest to be nil")
5050
}
5151
continue
@@ -66,11 +66,11 @@ func TestSplitFirstLast(t *testing.T) {
6666
}
6767

6868
ci, m := SplitFirst(c.AsMultiaddr())
69-
if !ci.Equal(c) || !m.Empty() {
69+
if !ci.Equal(c) || m != nil {
7070
t.Error("split first on component failed")
7171
}
7272
m, ci = SplitLast(c.AsMultiaddr())
73-
if !ci.Equal(c) || !m.Empty() {
73+
if !ci.Equal(c) || m != nil {
7474
t.Error("split last on component failed")
7575
}
7676
cis := Split(c.AsMultiaddr())
@@ -80,13 +80,13 @@ func TestSplitFirstLast(t *testing.T) {
8080
m1, m2 := SplitFunc(c.AsMultiaddr(), func(c Component) bool {
8181
return true
8282
})
83-
if !m1.Empty() || !m2.Equal(c.AsMultiaddr()) {
83+
if m1 != nil || !m2.Equal(c.AsMultiaddr()) {
8484
t.Error("split func(true) on component failed")
8585
}
8686
m1, m2 = SplitFunc(c.AsMultiaddr(), func(c Component) bool {
8787
return false
8888
})
89-
if !m1.Equal(c.AsMultiaddr()) || !m2.Empty() {
89+
if !m1.Equal(c.AsMultiaddr()) || m2 != nil {
9090
t.Error("split func(false) on component failed")
9191
}
9292

0 commit comments

Comments
 (0)