From 67b5090a10ae450bb58291ab9a2eb2febe89da1d Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Fri, 21 Feb 2025 16:05:22 -0800 Subject: [PATCH 1/6] Backwards compatible Encapsulate/Decapsulate/Join --- codec.go | 33 ++++++++++++++--------- component.go | 68 ++++++++++++++++++++++++++--------------------- multiaddr.go | 18 ++++++++++--- multiaddr_test.go | 45 ++++++++++++++++++++++++++----- util.go | 9 ++++++- util_test.go | 8 +++--- 6 files changed, 125 insertions(+), 56 deletions(-) diff --git a/codec.go b/codec.go index bdbeba6..1374aff 100644 --- a/codec.go +++ b/codec.go @@ -67,31 +67,36 @@ func stringToBytes(s string) ([]byte, error) { return b.Bytes(), nil } -func readComponent(b []byte) (int, Component, error) { +func readComponent(b []byte) (int, *Component, error) { var offset int code, n, err := ReadVarintCode(b) if err != nil { - return 0, Component{}, err + return 0, nil, err } offset += n p := ProtocolWithCode(code) if p.Code == 0 { - return 0, Component{}, fmt.Errorf("no protocol with code %d", code) + return 0, nil, fmt.Errorf("no protocol with code %d", code) } pPtr := protocolPtrByCode[code] if pPtr == nil { - return 0, Component{}, fmt.Errorf("no protocol with code %d", code) + return 0, nil, fmt.Errorf("no protocol with code %d", code) } if p.Size == 0 { - c, err := validateComponent(Component{ + c := &Component{ bytes: string(b[:offset]), valueStartIdx: offset, protocol: pPtr, - }) + } + + err := validateComponent(c) + if err != nil { + return 0, nil, err + } - return offset, c, err + return offset, c, nil } var size int @@ -100,7 +105,7 @@ func readComponent(b []byte) (int, Component, error) { var n int size, n, err = ReadVarintCode(b[offset:]) if err != nil { - return 0, Component{}, err + return 0, nil, err } offset += n } else { @@ -109,14 +114,18 @@ func readComponent(b []byte) (int, Component, error) { } if len(b[offset:]) < size || size <= 0 { - return 0, Component{}, fmt.Errorf("invalid value for size %d", len(b[offset:])) + return 0, nil, fmt.Errorf("invalid value for size %d", len(b[offset:])) } - c, err := validateComponent(Component{ + c := &Component{ bytes: string(b[:offset+size]), protocol: pPtr, valueStartIdx: offset, - }) + } + err = validateComponent(c) + if err != nil { + return 0, nil, err + } return offset + size, c, err } @@ -142,7 +151,7 @@ func readMultiaddr(b []byte) (int, Multiaddr, error) { return bytesRead, nil, fmt.Errorf("unexpected component after path component") } sawPathComponent = c.protocol.Path - res = append(res, c) + res = append(res, *c) } return bytesRead, res, nil } diff --git a/component.go b/component.go index d25f06a..ae6615c 100644 --- a/component.go +++ b/component.go @@ -26,11 +26,11 @@ func (c *Component) AsMultiaddr() Multiaddr { return []Component{*c} } -func (c *Component) Encapsulate(o Multiaddr) Multiaddr { +func (c *Component) Encapsulate(o asMultiaddr) Multiaddr { return c.AsMultiaddr().Encapsulate(o) } -func (c *Component) Decapsulate(o Multiaddr) Multiaddr { +func (c *Component) Decapsulate(o asMultiaddr) Multiaddr { return c.AsMultiaddr().Decapsulate(o) } @@ -63,7 +63,7 @@ func (c *Component) UnmarshalBinary(data []byte) error { if err != nil { return err } - *c = comp + *c = *comp return nil } @@ -87,7 +87,7 @@ func (c *Component) UnmarshalText(data []byte) error { if err != nil { return err } - *c = comp + *c = *comp return nil } @@ -236,24 +236,24 @@ func (c *Component) writeTo(b *strings.Builder) { } // NewComponent constructs a new multiaddr component -func NewComponent(protocol, value string) (Component, error) { +func NewComponent(protocol, value string) (*Component, error) { p := ProtocolWithName(protocol) if p.Code == 0 { - return Component{}, fmt.Errorf("unsupported protocol: %s", protocol) + return nil, fmt.Errorf("unsupported protocol: %s", protocol) } if p.Transcoder != nil { bts, err := p.Transcoder.StringToBytes(value) if err != nil { - return Component{}, err + return nil, err } return newComponent(p, bts) } else if value != "" { - return Component{}, fmt.Errorf("protocol %s doesn't take a value", p.Name) + return nil, fmt.Errorf("protocol %s doesn't take a value", p.Name) } return newComponent(p, nil) } -func newComponent(protocol Protocol, bvalue []byte) (Component, error) { +func newComponent(protocol Protocol, bvalue []byte) (*Component, error) { protocolPtr := protocolPtrByCode[protocol.Code] if protocolPtr == nil { protocolPtr = &protocol @@ -274,71 +274,79 @@ func newComponent(protocol Protocol, bvalue []byte) (Component, error) { // Shouldn't happen if len(maddr) != offset+len(bvalue) { - return Component{}, fmt.Errorf("component size mismatch: %d != %d", len(maddr), offset+len(bvalue)) + return nil, fmt.Errorf("component size mismatch: %d != %d", len(maddr), offset+len(bvalue)) } - return validateComponent( - Component{ - bytes: string(maddr), - protocol: protocolPtr, - valueStartIdx: offset, - }) + c := &Component{ + bytes: string(maddr), + protocol: protocolPtr, + valueStartIdx: offset, + } + + err := validateComponent(c) + if err != nil { + return nil, err + } + return c, nil } // validateComponent MUST be called after creating a non-zero Component. // It ensures that we will be able to call all methods on Component without // error. -func validateComponent(c Component) (Component, error) { +func validateComponent(c *Component) error { + if c == nil { + return errNilPtr + } if c.protocol == nil { - return Component{}, fmt.Errorf("component is missing its protocol") + return fmt.Errorf("component is missing its protocol") } if c.valueStartIdx > len(c.bytes) { - return Component{}, fmt.Errorf("component valueStartIdx is greater than the length of the component's bytes") + return fmt.Errorf("component valueStartIdx is greater than the length of the component's bytes") } if len(c.protocol.VCode) == 0 { - return Component{}, fmt.Errorf("Component is missing its protocol's VCode field") + return fmt.Errorf("Component is missing its protocol's VCode field") } if len(c.bytes) < len(c.protocol.VCode) { - return Component{}, fmt.Errorf("component size mismatch: %d != %d", len(c.bytes), len(c.protocol.VCode)) + return fmt.Errorf("component size mismatch: %d != %d", len(c.bytes), len(c.protocol.VCode)) } if !bytes.Equal([]byte(c.bytes[:len(c.protocol.VCode)]), c.protocol.VCode) { - return Component{}, fmt.Errorf("component's VCode field is invalid: %v != %v", []byte(c.bytes[:len(c.protocol.VCode)]), c.protocol.VCode) + return fmt.Errorf("component's VCode field is invalid: %v != %v", []byte(c.bytes[:len(c.protocol.VCode)]), c.protocol.VCode) } if c.protocol.Size < 0 { size, n, err := ReadVarintCode([]byte(c.bytes[len(c.protocol.VCode):])) if err != nil { - return Component{}, err + return err } if size != len(c.bytes[c.valueStartIdx:]) { - return Component{}, fmt.Errorf("component value size mismatch: %d != %d", size, len(c.bytes[c.valueStartIdx:])) + return fmt.Errorf("component value size mismatch: %d != %d", size, len(c.bytes[c.valueStartIdx:])) } if len(c.protocol.VCode)+n+size != len(c.bytes) { - return Component{}, fmt.Errorf("component size mismatch: %d != %d", len(c.protocol.VCode)+n+size, len(c.bytes)) + return fmt.Errorf("component size mismatch: %d != %d", len(c.protocol.VCode)+n+size, len(c.bytes)) } } else { // Fixed size value size := c.protocol.Size / 8 if size != len(c.bytes[c.valueStartIdx:]) { - return Component{}, fmt.Errorf("component value size mismatch: %d != %d", size, len(c.bytes[c.valueStartIdx:])) + return fmt.Errorf("component value size mismatch: %d != %d", size, len(c.bytes[c.valueStartIdx:])) } if len(c.protocol.VCode)+size != len(c.bytes) { - return Component{}, fmt.Errorf("component size mismatch: %d != %d", len(c.protocol.VCode)+size, len(c.bytes)) + return fmt.Errorf("component size mismatch: %d != %d", len(c.protocol.VCode)+size, len(c.bytes)) } } _, err := c.valueAndErr() if err != nil { - return Component{}, err + return err } if c.protocol.Transcoder != nil { err = c.protocol.Transcoder.ValidateBytes([]byte(c.bytes[c.valueStartIdx:])) if err != nil { - return Component{}, err + return err } } - return c, nil + return nil } diff --git a/multiaddr.go b/multiaddr.go index 3a8a03b..8768821 100644 --- a/multiaddr.go +++ b/multiaddr.go @@ -181,9 +181,17 @@ func (m Multiaddr) Protocols() []Protocol { return out } +type asMultiaddr interface { + AsMultiaddr() Multiaddr +} + +func (m Multiaddr) AsMultiaddr() Multiaddr { + return m +} + // Encapsulate wraps a given Multiaddr, returning the resulting joined Multiaddr -func (m Multiaddr) Encapsulate(o Multiaddr) Multiaddr { - return Join(m, o) +func (m Multiaddr) Encapsulate(other asMultiaddr) Multiaddr { + return Join(m, other) } func (m Multiaddr) EncapsulateC(c *Component) Multiaddr { @@ -197,7 +205,11 @@ func (m Multiaddr) EncapsulateC(c *Component) Multiaddr { } // Decapsulate unwraps Multiaddr up until the given Multiaddr is found. -func (m Multiaddr) Decapsulate(rightParts Multiaddr) Multiaddr { +func (m Multiaddr) Decapsulate(rightPartsAny asMultiaddr) Multiaddr { + if rightPartsAny == nil { + return m + } + rightParts := rightPartsAny.AsMultiaddr() leftParts := m lastIndex := -1 diff --git a/multiaddr_test.go b/multiaddr_test.go index 28b068f..52f46d7 100644 --- a/multiaddr_test.go +++ b/multiaddr_test.go @@ -79,6 +79,16 @@ func TestReturnsNilOnEmpty(t *testing.T) { require.Nil(t, a) } +func TestJoinWithComponents(t *testing.T) { + var m Multiaddr + c, err := NewComponent("ip4", "127.0.0.1") + require.NoError(t, err) + + expected := "/ip4/127.0.0.1" + require.Equal(t, expected, Join(m, c).String()) + +} + func TestConstructFails(t *testing.T) { cases := []string{ "/ip4", @@ -520,6 +530,19 @@ func TestEncapsulate(t *testing.T) { if d != nil { t.Error("decapsulate /ip4 failed: ", d) } + + t.Run("Encapsulating with components", func(t *testing.T) { + left, last := SplitLast(m) + joined := left.Encapsulate(last) + require.True(t, joined.Equal(m)) + + first, rest := SplitFirst(m) + joined = first.Encapsulate(rest) + require.True(t, joined.Equal(m)) + // Component type + joined = (*first).Encapsulate(rest) + require.True(t, joined.Equal(m)) + }) } func TestDecapsulateComment(t *testing.T) { @@ -580,6 +603,16 @@ func TestDecapsulate(t *testing.T) { require.Equal(t, expected, actual) }) } + + for _, tc := range testcases { + t.Run("Decapsulating with components"+tc.left, func(t *testing.T) { + left, last := SplitLast(StringCast(tc.left)) + butLast := left.Decapsulate(last) + require.Equal(t, butLast.String(), left.String()) + // Round trip + require.Equal(t, tc.left, butLast.Encapsulate(last).String()) + }) + } } func assertValueForProto(t *testing.T, a Multiaddr, p int, exp string) { @@ -949,7 +982,7 @@ func TestUseNilComponent(t *testing.T) { foo.AsMultiaddr() foo.Encapsulate(nil) foo.Decapsulate(nil) - foo.Empty() + require.True(t, foo.Empty()) foo.Bytes() foo.MarshalBinary() foo.MarshalJSON() @@ -1124,12 +1157,12 @@ func FuzzSplitRoundtrip(f *testing.F) { // Test SplitFirst first, rest := SplitFirst(addr) - joined := Join(first.AsMultiaddr(), rest) + joined := Join(first, rest) require.True(t, addr.Equal(joined), "SplitFirst and Join should round-trip") // Test SplitLast rest, last := SplitLast(addr) - joined = Join(rest, last.AsMultiaddr()) + joined = Join(rest, last) require.True(t, addr.Equal(joined), "SplitLast and Join should round-trip") p := addr.Protocols() @@ -1155,12 +1188,12 @@ func FuzzSplitRoundtrip(f *testing.F) { return c.Protocol().Code == proto.Code } beforeC, after := SplitFirst(addr) - joined = Join(beforeC.AsMultiaddr(), after) + joined = Join(beforeC, after) require.True(t, addr.Equal(joined)) tryPubMethods(after) before, afterC := SplitLast(addr) - joined = Join(before, afterC.AsMultiaddr()) + joined = Join(before, afterC) require.True(t, addr.Equal(joined)) tryPubMethods(before) @@ -1180,7 +1213,7 @@ func BenchmarkComponentValidation(b *testing.B) { } b.ReportAllocs() for i := 0; i < b.N; i++ { - _, err := validateComponent(comp) + err := validateComponent(comp) if err != nil { b.Fatal(err) } diff --git a/util.go b/util.go index 038c143..4f35ca8 100644 --- a/util.go +++ b/util.go @@ -25,7 +25,14 @@ func JoinComponents(cs ...Component) Multiaddr { // Join returns a combination of addresses. // Note: This copies all the components from the input Multiaddrs. Depending on // your use case, you may prefer to use `append(leftMA, rightMA...)` instead. -func Join(ms ...Multiaddr) Multiaddr { +func Join(msInterfaces ...asMultiaddr) Multiaddr { + ms := make([]Multiaddr, len(msInterfaces)) + for i, m := range msInterfaces { + if m == nil { + continue + } + ms[i] = m.AsMultiaddr() + } size := 0 for _, m := range ms { size += len(m) diff --git a/util_test.go b/util_test.go index 1409122..3494486 100644 --- a/util_test.go +++ b/util_test.go @@ -66,15 +66,15 @@ func TestSplitFirstLast(t *testing.T) { } ci, m := SplitFirst(c.AsMultiaddr()) - if !ci.Equal(&c) || m != nil { + if !ci.Equal(c) || m != nil { t.Error("split first on component failed") } m, ci = SplitLast(c.AsMultiaddr()) - if !ci.Equal(&c) || m != nil { + if !ci.Equal(c) || m != nil { t.Error("split last on component failed") } cis := Split(c.AsMultiaddr()) - if len(cis) != 1 || !cis[0].Equal(&c) { + if len(cis) != 1 || !cis[0].Equal(c) { t.Error("split on component failed") } m1, m2 := SplitFunc(c.AsMultiaddr(), func(c Component) bool { @@ -96,7 +96,7 @@ func TestSplitFirstLast(t *testing.T) { t.Error("expected exactly one component") } i++ - if !ci.Equal(&c) { + if !ci.Equal(c) { t.Error("foreach on component failed") } return true From 0f95b11264313ad7120764a572616302ed00dd14 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Fri, 21 Feb 2025 16:28:46 -0800 Subject: [PATCH 2/6] remove EncapsulateC --- multiaddr.go | 10 ---------- multiaddr_test.go | 2 +- v015-MIGRATION.md | 6 ++++-- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/multiaddr.go b/multiaddr.go index 8768821..50d6118 100644 --- a/multiaddr.go +++ b/multiaddr.go @@ -194,16 +194,6 @@ func (m Multiaddr) Encapsulate(other asMultiaddr) Multiaddr { return Join(m, other) } -func (m Multiaddr) EncapsulateC(c *Component) Multiaddr { - if c.Empty() { - return m - } - out := make([]Component, 0, len(m)+1) - out = append(out, m...) - out = append(out, *c) - return out -} - // Decapsulate unwraps Multiaddr up until the given Multiaddr is found. func (m Multiaddr) Decapsulate(rightPartsAny asMultiaddr) Multiaddr { if rightPartsAny == nil { diff --git a/multiaddr_test.go b/multiaddr_test.go index 52f46d7..e28bb92 100644 --- a/multiaddr_test.go +++ b/multiaddr_test.go @@ -1000,7 +1000,7 @@ func TestUseNilComponent(t *testing.T) { _ = foo.String() var m Multiaddr = nil - m.EncapsulateC(foo) + m.Encapsulate(foo) } func TestFilterAddrs(t *testing.T) { diff --git a/v015-MIGRATION.md b/v015-MIGRATION.md index ab75a39..3af7180 100644 --- a/v015-MIGRATION.md +++ b/v015-MIGRATION.md @@ -2,7 +2,7 @@ - There is no `Multiaddr` interface type. - Multiaddr is now a concrete type. Not an interface. -- Empty Multiaddrs/ should be checked with `.Empty()`, not `== nil`. This is similar to how slices should be checked with `len(s) == 0` rather than `s == nil`. +- Empty Multiaddrs/Component should generally be checked with `.Empty()`, not `== nil`. This is similar to how slices should be checked with `len(s) == 0` rather than `s == nil`. - Components do not implement `Multiaddr` as there is no `Multiaddr` to implement. - `Multiaddr` can no longer be a key in a Map. If you want unique Multiaddrs, use `Multiaddr.String()` as the key, otherwise you can use the pointer value `*Multiaddr`. @@ -12,4 +12,6 @@ ## Migration tips for v0.15 -- If trying to encapsulate a Component to a Multiaddr, use `m.encapsulateC(c)`, instead of the old form of `m.Encapsulate(c)`. `Encapsulate` now only accepts a `Multiaddr`. `EncapsulateC` accepts a `Component`. +- If your use case supports it, prefer `append` to append a Component to a + Multiaddr rather than using `Encapsulate`. It's much faster as it does not do + a defensive copy. From c4d0b7843c27b52b3a1d1af2bc41000dbeb35437 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Fri, 21 Feb 2025 18:19:19 -0800 Subject: [PATCH 3/6] feat: Add Multiaddr.AppendComponent --- multiaddr.go | 12 ++++++++++++ multiaddr_test.go | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/multiaddr.go b/multiaddr.go index 50d6118..f786ac4 100644 --- a/multiaddr.go +++ b/multiaddr.go @@ -189,6 +189,18 @@ func (m Multiaddr) AsMultiaddr() Multiaddr { return m } +// AppendComponent is the same as using `append(m, *c)`, but with a safety check +// for a nil Component. +func (m Multiaddr) AppendComponent(cs ...*Component) Multiaddr { + for _, c := range cs { + if c == nil { + continue + } + m = append(m, *c) + } + return m +} + // Encapsulate wraps a given Multiaddr, returning the resulting joined Multiaddr func (m Multiaddr) Encapsulate(other asMultiaddr) Multiaddr { return Join(m, other) diff --git a/multiaddr_test.go b/multiaddr_test.go index e28bb92..c1bdee3 100644 --- a/multiaddr_test.go +++ b/multiaddr_test.go @@ -627,6 +627,17 @@ func assertValueForProto(t *testing.T, a Multiaddr, p int, exp string) { } } +func TestAppendComponent(t *testing.T) { + var m Multiaddr + res := m.AppendComponent(nil) + require.Equal(t, m, res) + + c, err := NewComponent("ip4", "127.0.0.1") + require.NoError(t, err) + res = m.AppendComponent(c) + require.Equal(t, "/ip4/127.0.0.1", res.String()) +} + func TestGetValue(t *testing.T) { a := newMultiaddr(t, "/ip4/127.0.0.1/utp/tcp/5555/udp/1234/tls/utp/ipfs/QmbHVEEepCi7rn7VL7Exxpd2Ci9NNB6ifvqwhsrbRMgQFP") assertValueForProto(t, a, P_IP4, "127.0.0.1") From f41d6e62666f8297134b57efd3c0e93a977484ea Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Mon, 24 Feb 2025 11:18:25 -0800 Subject: [PATCH 4/6] remove .Empty (#274) prefer the simpler `len` check for Multiaddr and `== nil` for `*Component`. --- component.go | 12 +----------- multiaddr.go | 12 ------------ multiaddr_test.go | 15 +++++++-------- net/ip.go | 10 +++++----- util.go | 31 +++++++------------------------ util_test.go | 12 ++++++------ 6 files changed, 26 insertions(+), 66 deletions(-) diff --git a/component.go b/component.go index ae6615c..ca796f6 100644 --- a/component.go +++ b/component.go @@ -20,7 +20,7 @@ type Component struct { } func (c *Component) AsMultiaddr() Multiaddr { - if c.Empty() { + if c == nil { return nil } return []Component{*c} @@ -34,13 +34,6 @@ func (c *Component) Decapsulate(o asMultiaddr) Multiaddr { return c.AsMultiaddr().Decapsulate(o) } -func (c *Component) Empty() bool { - if c == nil { - return true - } - return len(c.bytes) == 0 -} - func (c *Component) Bytes() []byte { if c == nil { return nil @@ -180,9 +173,6 @@ func (c *Component) Value() string { if c == nil { return "" } - if c.Empty() { - return "" - } // This Component MUST have been checked by validateComponent when created value, _ := c.valueAndErr() return value diff --git a/multiaddr.go b/multiaddr.go index f786ac4..253e20e 100644 --- a/multiaddr.go +++ b/multiaddr.go @@ -25,18 +25,6 @@ func (m Multiaddr) copy() Multiaddr { return out } -func (m Multiaddr) Empty() bool { - if len(m) == 0 { - return true - } - for _, c := range m { - if !c.Empty() { - return false - } - } - return true -} - // NewMultiaddr parses and validates an input string, returning a *Multiaddr func NewMultiaddr(s string) (a Multiaddr, err error) { defer func() { diff --git a/multiaddr_test.go b/multiaddr_test.go index c1bdee3..c9d4b68 100644 --- a/multiaddr_test.go +++ b/multiaddr_test.go @@ -32,7 +32,6 @@ func TestReturnsNilOnEmpty(t *testing.T) { require.Zero(t, len(a.Protocols())) require.Nil(t, a) require.Nil(t, c) - require.True(t, c.Empty()) // Test that empty multiaddr from various operations returns nil a = StringCast("/ip4/1.2.3.4/tcp/1234") @@ -45,7 +44,6 @@ func TestReturnsNilOnEmpty(t *testing.T) { c, a = SplitFirst(nil) require.Nil(t, a) require.Nil(t, c) - require.True(t, c.Empty()) a = StringCast("/ip4/1.2.3.4/tcp/1234") a = a.Decapsulate(a) @@ -72,7 +70,8 @@ func TestReturnsNilOnEmpty(t *testing.T) { _, err := NewMultiaddr("") require.Error(t, err) - a = JoinComponents() + var nilMultiaddr Multiaddr + a = nilMultiaddr.AppendComponent() require.Nil(t, a) a = Join() @@ -425,7 +424,7 @@ func TestBytesSplitAndJoin(t *testing.T) { } } - joined := JoinComponents(split...) + joined := append(Multiaddr{}, split...) if !m.Equal(joined) { t.Errorf("joined components failed: %s != %s", m, joined) } @@ -914,7 +913,7 @@ func TestComponentBinaryMarshaler(t *testing.T) { t.Fatal(err) } - comp2 := Component{} + var comp2 Component if err = comp2.UnmarshalBinary(b); err != nil { t.Fatal(err) } @@ -933,7 +932,7 @@ func TestComponentTextMarshaler(t *testing.T) { t.Fatal(err) } - comp2 := Component{} + var comp2 Component if err = comp2.UnmarshalText(b); err != nil { t.Fatal(err) } @@ -952,7 +951,7 @@ func TestComponentJSONMarshaler(t *testing.T) { t.Fatal(err) } - comp2 := Component{} + var comp2 Component if err = comp2.UnmarshalJSON(b); err != nil { t.Fatal(err) } @@ -993,7 +992,7 @@ func TestUseNilComponent(t *testing.T) { foo.AsMultiaddr() foo.Encapsulate(nil) foo.Decapsulate(nil) - require.True(t, foo.Empty()) + require.True(t, foo == nil) foo.Bytes() foo.MarshalBinary() foo.MarshalJSON() diff --git a/net/ip.go b/net/ip.go index e8acecb..def9321 100644 --- a/net/ip.go +++ b/net/ip.go @@ -64,7 +64,7 @@ func IsIPLoopback(m ma.Multiaddr) bool { return false } c, _ := ma.SplitFirst(m) - if c.Empty() { + if c == nil { return false } switch c.Protocol().Code { @@ -83,7 +83,7 @@ func IsIP6LinkLocal(m ma.Multiaddr) bool { return false } c, _ := ma.SplitFirst(m) - if c.Empty() || c.Protocol().Code != ma.P_IP6 { + if c == nil || c.Protocol().Code != ma.P_IP6 { return false } ip := net.IP(c.RawValue()) @@ -106,11 +106,11 @@ func IsIPUnspecified(m ma.Multiaddr) bool { // else return m func zoneless(m ma.Multiaddr) ma.Multiaddr { head, tail := ma.SplitFirst(m) - if head.Empty() { + if head == nil { return nil } if head.Protocol().Code == ma.P_IP6ZONE { - if tail.Empty() { + if tail == nil { return nil } tailhead, _ := ma.SplitFirst(tail) @@ -127,6 +127,6 @@ func zoneless(m ma.Multiaddr) ma.Multiaddr { // used for NAT64 Translation. See RFC 6052 func IsNAT64IPv4ConvertedIPv6Addr(addr ma.Multiaddr) bool { c, _ := ma.SplitFirst(addr) - return !c.Empty() && c.Protocol().Code == ma.P_IP6 && + return c != nil && c.Protocol().Code == ma.P_IP6 && inAddrRange(c.RawValue(), nat64) } diff --git a/util.go b/util.go index 4f35ca8..4134e04 100644 --- a/util.go +++ b/util.go @@ -9,19 +9,6 @@ func Split(m Multiaddr) []Component { return m } -func JoinComponents(cs ...Component) Multiaddr { - if len(cs) == 0 { - return nil - } - out := make([]Component, 0, len(cs)) - for _, c := range cs { - if !c.Empty() { - out = append(out, c) - } - } - return out -} - // Join returns a combination of addresses. // Note: This copies all the components from the input Multiaddrs. Depending on // your use case, you may prefer to use `append(leftMA, rightMA...)` instead. @@ -43,11 +30,7 @@ func Join(msInterfaces ...asMultiaddr) Multiaddr { out := make([]Component, 0, size) for _, m := range ms { - for _, c := range m { - if !c.Empty() { - out = append(out, c) - } - } + out = append(out, m...) } return out } @@ -72,7 +55,7 @@ func StringCast(s string) Multiaddr { // SplitFirst returns the first component and the rest of the multiaddr. func SplitFirst(m Multiaddr) (*Component, Multiaddr) { - if m.Empty() { + if len(m) == 0 { return nil, nil } if len(m) == 1 { @@ -85,7 +68,7 @@ func SplitFirst(m Multiaddr) (*Component, Multiaddr) { // SplitLast returns the rest of the multiaddr and the last component. func SplitLast(m Multiaddr) (Multiaddr, *Component) { - if m.Empty() { + if len(m) == 0 { return nil, nil } if len(m) == 1 { @@ -101,7 +84,7 @@ func SplitLast(m Multiaddr) (Multiaddr, *Component) { // component on which the callback first returns will be included in the // *second* multiaddr. func SplitFunc(m Multiaddr, cb func(Component) bool) (Multiaddr, Multiaddr) { - if m.Empty() { + if len(m) == 0 { return nil, nil } @@ -113,10 +96,10 @@ func SplitFunc(m Multiaddr, cb func(Component) bool) (Multiaddr, Multiaddr) { } } pre, post := m[:idx], m[idx:] - if pre.Empty() { + if len(pre) == 0 { pre = nil } - if post.Empty() { + if len(post) == 0 { post = nil } // defensive copy. Users can avoid by doing the split themselves. @@ -128,7 +111,7 @@ func SplitFunc(m Multiaddr, cb func(Component) bool) (Multiaddr, Multiaddr) { // This function iterates over components. // Return true to continue iteration, false to stop. // -// Prefer to use a standard for range loop instead +// Prefer a standard for range loop instead // e.g. `for _, c := range m { ... }` func ForEach(m Multiaddr, cb func(c Component) bool) { for _, c := range m { diff --git a/util_test.go b/util_test.go index 3494486..318c924 100644 --- a/util_test.go +++ b/util_test.go @@ -21,8 +21,8 @@ func TestSplitFirstLast(t *testing.T) { head, tail := SplitFirst(addr) rest, last := SplitLast(addr) if len(x) == 0 { - if !head.Empty() { - t.Error("expected head to be empty") + if head != nil { + t.Error("expected head to be nil") } if tail != nil { t.Error("expected tail to be nil") @@ -30,8 +30,8 @@ func TestSplitFirstLast(t *testing.T) { if rest != nil { t.Error("expected rest to be nil") } - if !last.Empty() { - t.Error("expected last to be empty") + if last != nil { + t.Error("expected last to be nil") } continue } @@ -122,7 +122,7 @@ func TestSplitFunc(t *testing.T) { return c.AsMultiaddr().Equal(target) }) if i == 0 { - if !a.Empty() { + if a != nil { t.Error("expected nil addr") } } else { @@ -135,7 +135,7 @@ func TestSplitFunc(t *testing.T) { } } a, b := SplitFunc(addr, func(_ Component) bool { return false }) - if !a.Equal(addr) || !b.Empty() { + if !a.Equal(addr) || b != nil { t.Error("should not have split") } } From 9424619c4cef225ea9b51af2ae9222902293cd11 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Mon, 24 Feb 2025 11:21:04 -0800 Subject: [PATCH 5/6] export AsMultiaddrer interface --- component.go | 4 ++-- multiaddr.go | 6 +++--- util.go | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/component.go b/component.go index ca796f6..1bba65c 100644 --- a/component.go +++ b/component.go @@ -26,11 +26,11 @@ func (c *Component) AsMultiaddr() Multiaddr { return []Component{*c} } -func (c *Component) Encapsulate(o asMultiaddr) Multiaddr { +func (c *Component) Encapsulate(o AsMultiaddrer) Multiaddr { return c.AsMultiaddr().Encapsulate(o) } -func (c *Component) Decapsulate(o asMultiaddr) Multiaddr { +func (c *Component) Decapsulate(o AsMultiaddrer) Multiaddr { return c.AsMultiaddr().Decapsulate(o) } diff --git a/multiaddr.go b/multiaddr.go index 253e20e..22b70fc 100644 --- a/multiaddr.go +++ b/multiaddr.go @@ -169,7 +169,7 @@ func (m Multiaddr) Protocols() []Protocol { return out } -type asMultiaddr interface { +type AsMultiaddrer interface { AsMultiaddr() Multiaddr } @@ -190,12 +190,12 @@ func (m Multiaddr) AppendComponent(cs ...*Component) Multiaddr { } // Encapsulate wraps a given Multiaddr, returning the resulting joined Multiaddr -func (m Multiaddr) Encapsulate(other asMultiaddr) Multiaddr { +func (m Multiaddr) Encapsulate(other AsMultiaddrer) Multiaddr { return Join(m, other) } // Decapsulate unwraps Multiaddr up until the given Multiaddr is found. -func (m Multiaddr) Decapsulate(rightPartsAny asMultiaddr) Multiaddr { +func (m Multiaddr) Decapsulate(rightPartsAny AsMultiaddrer) Multiaddr { if rightPartsAny == nil { return m } diff --git a/util.go b/util.go index 4134e04..5157b13 100644 --- a/util.go +++ b/util.go @@ -12,7 +12,7 @@ func Split(m Multiaddr) []Component { // Join returns a combination of addresses. // Note: This copies all the components from the input Multiaddrs. Depending on // your use case, you may prefer to use `append(leftMA, rightMA...)` instead. -func Join(msInterfaces ...asMultiaddr) Multiaddr { +func Join(msInterfaces ...AsMultiaddrer) Multiaddr { ms := make([]Multiaddr, len(msInterfaces)) for i, m := range msInterfaces { if m == nil { From 84974b80f4d32194aed37f9179669670913127f0 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Mon, 24 Feb 2025 11:32:42 -0800 Subject: [PATCH 6/6] rename AsMultiaddr to Multiaddr Export Multiaddrer interface --- component.go | 10 +++++----- multiaddr.go | 13 +++++++------ multiaddr_test.go | 4 ++-- net/convert.go | 6 +++--- net/resolve.go | 2 +- util.go | 4 ++-- util_test.go | 22 +++++++++++----------- 7 files changed, 31 insertions(+), 30 deletions(-) diff --git a/component.go b/component.go index 1bba65c..6e8a640 100644 --- a/component.go +++ b/component.go @@ -19,19 +19,19 @@ type Component struct { valueStartIdx int // Index of the first byte of the Component's value in the bytes array } -func (c *Component) AsMultiaddr() Multiaddr { +func (c *Component) Multiaddr() Multiaddr { if c == nil { return nil } return []Component{*c} } -func (c *Component) Encapsulate(o AsMultiaddrer) Multiaddr { - return c.AsMultiaddr().Encapsulate(o) +func (c *Component) Encapsulate(o Multiaddrer) Multiaddr { + return c.Multiaddr().Encapsulate(o) } -func (c *Component) Decapsulate(o AsMultiaddrer) Multiaddr { - return c.AsMultiaddr().Decapsulate(o) +func (c *Component) Decapsulate(o Multiaddrer) Multiaddr { + return c.Multiaddr().Decapsulate(o) } func (c *Component) Bytes() []byte { diff --git a/multiaddr.go b/multiaddr.go index 22b70fc..2565f51 100644 --- a/multiaddr.go +++ b/multiaddr.go @@ -169,11 +169,12 @@ func (m Multiaddr) Protocols() []Protocol { return out } -type AsMultiaddrer interface { - AsMultiaddr() Multiaddr +type Multiaddrer interface { + // Multiaddr returns the Multiaddr representation + Multiaddr() Multiaddr } -func (m Multiaddr) AsMultiaddr() Multiaddr { +func (m Multiaddr) Multiaddr() Multiaddr { return m } @@ -190,16 +191,16 @@ func (m Multiaddr) AppendComponent(cs ...*Component) Multiaddr { } // Encapsulate wraps a given Multiaddr, returning the resulting joined Multiaddr -func (m Multiaddr) Encapsulate(other AsMultiaddrer) Multiaddr { +func (m Multiaddr) Encapsulate(other Multiaddrer) Multiaddr { return Join(m, other) } // Decapsulate unwraps Multiaddr up until the given Multiaddr is found. -func (m Multiaddr) Decapsulate(rightPartsAny AsMultiaddrer) Multiaddr { +func (m Multiaddr) Decapsulate(rightPartsAny Multiaddrer) Multiaddr { if rightPartsAny == nil { return m } - rightParts := rightPartsAny.AsMultiaddr() + rightParts := rightPartsAny.Multiaddr() leftParts := m lastIndex := -1 diff --git a/multiaddr_test.go b/multiaddr_test.go index c9d4b68..54fdc4c 100644 --- a/multiaddr_test.go +++ b/multiaddr_test.go @@ -322,7 +322,7 @@ func TestNilInterface(t *testing.T) { // Test components c, _ := SplitFirst(m1) - c.AsMultiaddr().Equal(m2) + c.Multiaddr().Equal(m2) c.Encapsulate(m2) c.Decapsulate(m2) @@ -989,7 +989,7 @@ func TestUseNil(t *testing.T) { func TestUseNilComponent(t *testing.T) { var foo *Component - foo.AsMultiaddr() + foo.Multiaddr() foo.Encapsulate(nil) foo.Decapsulate(nil) require.True(t, foo == nil) diff --git a/net/convert.go b/net/convert.go index be320d3..8056451 100644 --- a/net/convert.go +++ b/net/convert.go @@ -108,13 +108,13 @@ func FromIPAndZone(ip net.IP, zone string) (ma.Multiaddr, error) { if err != nil { return nil, err } - return c.AsMultiaddr(), nil + return c.Multiaddr(), nil case ip.To16() != nil: ip6C, err := ma.NewComponent("ip6", ip.String()) if err != nil { return nil, err } - ip6 := ip6C.AsMultiaddr() + ip6 := ip6C.Multiaddr() if zone == "" { return ip6, nil } else { @@ -362,5 +362,5 @@ func parseUnixNetAddr(a net.Addr) (ma.Multiaddr, error) { if err != nil { return nil, err } - return c.AsMultiaddr(), nil + return c.Multiaddr(), nil } diff --git a/net/resolve.go b/net/resolve.go index 0b43d08..cd98fd8 100644 --- a/net/resolve.go +++ b/net/resolve.go @@ -14,7 +14,7 @@ func ResolveUnspecifiedAddress(resolve ma.Multiaddr, ifaceAddrs []ma.Multiaddr) first, rest := ma.SplitFirst(resolve) // if first component (ip) is not unspecified, use it as is. - if !IsIPUnspecified(first.AsMultiaddr()) { + if !IsIPUnspecified(first.Multiaddr()) { return []ma.Multiaddr{resolve}, nil } diff --git a/util.go b/util.go index 5157b13..d063e39 100644 --- a/util.go +++ b/util.go @@ -12,13 +12,13 @@ func Split(m Multiaddr) []Component { // Join returns a combination of addresses. // Note: This copies all the components from the input Multiaddrs. Depending on // your use case, you may prefer to use `append(leftMA, rightMA...)` instead. -func Join(msInterfaces ...AsMultiaddrer) Multiaddr { +func Join(msInterfaces ...Multiaddrer) Multiaddr { ms := make([]Multiaddr, len(msInterfaces)) for i, m := range msInterfaces { if m == nil { continue } - ms[i] = m.AsMultiaddr() + ms[i] = m.Multiaddr() } size := 0 for _, m := range ms { diff --git a/util_test.go b/util_test.go index 318c924..365ba41 100644 --- a/util_test.go +++ b/util_test.go @@ -35,10 +35,10 @@ func TestSplitFirstLast(t *testing.T) { } continue } - if !head.AsMultiaddr().Equal(StringCast(x[0])) { + if !head.Multiaddr().Equal(StringCast(x[0])) { t.Errorf("expected %s to be %s", head, x[0]) } - if !last.AsMultiaddr().Equal(StringCast(x[len(x)-1])) { + if !last.Multiaddr().Equal(StringCast(x[len(x)-1])) { t.Errorf("expected %s to be %s", head, x[len(x)-1]) } if len(x) == 1 { @@ -65,33 +65,33 @@ func TestSplitFirstLast(t *testing.T) { t.Fatal(err) } - ci, m := SplitFirst(c.AsMultiaddr()) + ci, m := SplitFirst(c.Multiaddr()) if !ci.Equal(c) || m != nil { t.Error("split first on component failed") } - m, ci = SplitLast(c.AsMultiaddr()) + m, ci = SplitLast(c.Multiaddr()) if !ci.Equal(c) || m != nil { t.Error("split last on component failed") } - cis := Split(c.AsMultiaddr()) + cis := Split(c.Multiaddr()) if len(cis) != 1 || !cis[0].Equal(c) { t.Error("split on component failed") } - m1, m2 := SplitFunc(c.AsMultiaddr(), func(c Component) bool { + m1, m2 := SplitFunc(c.Multiaddr(), func(c Component) bool { return true }) - if m1 != nil || !m2.Equal(c.AsMultiaddr()) { + if m1 != nil || !m2.Equal(c.Multiaddr()) { t.Error("split func(true) on component failed") } - m1, m2 = SplitFunc(c.AsMultiaddr(), func(c Component) bool { + m1, m2 = SplitFunc(c.Multiaddr(), func(c Component) bool { return false }) - if !m1.Equal(c.AsMultiaddr()) || m2 != nil { + if !m1.Equal(c.Multiaddr()) || m2 != nil { t.Error("split func(false) on component failed") } i := 0 - ForEach(c.AsMultiaddr(), func(ci Component) bool { + ForEach(c.Multiaddr(), func(ci Component) bool { if i != 0 { t.Error("expected exactly one component") } @@ -119,7 +119,7 @@ func TestSplitFunc(t *testing.T) { for i, cs := range x { target := StringCast(cs) a, b := SplitFunc(addr, func(c Component) bool { - return c.AsMultiaddr().Equal(target) + return c.Multiaddr().Equal(target) }) if i == 0 { if a != nil {