From 4a5dcd3a4d6f46a0424321aa75092b694ced4f24 Mon Sep 17 00:00:00 2001 From: Juan Batiz-Benet Date: Tue, 4 Nov 2014 23:20:17 -0800 Subject: [PATCH] Split: added split method --- codec.go | 24 ++++++++++++++++++++++++ interface.go | 6 ++++++ multiaddr.go | 16 ++++++++++++++++ multiaddr_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+) diff --git a/codec.go b/codec.go index a6cf991..d08544b 100644 --- a/codec.go +++ b/codec.go @@ -67,6 +67,30 @@ func bytesToString(b []byte) (ret string, err error) { return s, nil } +func bytesSplit(b []byte) (ret [][]byte, err error) { + // panic handler, in case we try accessing bytes incorrectly. + defer func() { + if e := recover(); e != nil { + ret = [][]byte{} + err = e.(error) + } + }() + + ret = [][]byte{} + for len(b) > 0 { + p := ProtocolWithCode(int(b[0])) + if p == nil { + return [][]byte{}, fmt.Errorf("no protocol with code %d", b[0]) + } + + length := 1 + (p.Size / 8) + ret = append(ret, b[:length]) + b = b[length:] + } + + return ret, nil +} + func addressStringToBytes(p *Protocol, s string) []byte { switch p.Code { diff --git a/interface.go b/interface.go index 6f57625..3ce6d2a 100644 --- a/interface.go +++ b/interface.go @@ -39,4 +39,10 @@ type Multiaddr interface { // /ip4/1.2.3.4/tcp/80 decapsulate /ip4/1.2.3.4 = /tcp/80 // Decapsulate(Multiaddr) Multiaddr + + // Split returns the sub-address portions of this multiaddr. + // + // m, _ := NewMultiaddr("/ip4/1.2.3.4/tcp/1234") + // m.Split() -> [/ip4/1.2.3.4, /tcp/1234] + Split() []Multiaddr } diff --git a/multiaddr.go b/multiaddr.go index 4ee63ca..17e7907 100644 --- a/multiaddr.go +++ b/multiaddr.go @@ -108,3 +108,19 @@ func (m *multiaddr) Decapsulate(o Multiaddr) Multiaddr { } return ma } + +// Split returns the sub-address portions of this multiaddr. +func (m *multiaddr) Split() []Multiaddr { + split, err := bytesSplit(m.bytes) + if err != nil { + panic(fmt.Errorf("invalid multiaddr %s", m.String())) + } + + addrs := make([]Multiaddr, len(split)) + for i, addr := range split { + c := make([]byte, len(addr)) + copy(c, addr) + addrs[i] = &multiaddr{bytes: c} + } + return addrs +} diff --git a/multiaddr_test.go b/multiaddr_test.go index 3a78204..dca43ab 100644 --- a/multiaddr_test.go +++ b/multiaddr_test.go @@ -91,6 +91,45 @@ func TestBytesToString(t *testing.T) { testString("/ip4/127.0.0.1/udp/1234", "047f0000011104d2") } +func TestBytesSplit(t *testing.T) { + + testString := func(s string, res []string) { + m, err := NewMultiaddr(s) + if err != nil { + t.Error("failed to convert", s) + } + + split := m.Split() + if len(split) != len(res) { + t.Error("not enough split components", split) + return + } + + for i, a := range split { + if a.String() != res[i] { + t.Errorf("split component failed: %s != %s", a, res[i]) + } + } + + // modifying underlying bytes is fine. + m2 := m.(*multiaddr) + for i := range m2.bytes { + m2.bytes[i] = 0 + } + + for i, a := range split { + if a.String() != res[i] { + t.Errorf("split component failed: %s != %s", a, res[i]) + } + } + + } + + testString("/ip4/1.2.3.4/udp/1234", []string{"/ip4/1.2.3.4", "/udp/1234"}) + testString("/ip4/1.2.3.4/tcp/1/ip4/2.3.4.5/udp/2", + []string{"/ip4/1.2.3.4", "/tcp/1", "/ip4/2.3.4.5", "/udp/2"}) +} + func TestProtocols(t *testing.T) { m, err := NewMultiaddr("/ip4/127.0.0.1/udp/1234") if err != nil {