Split: added split method

This commit is contained in:
Juan Batiz-Benet 2014-11-04 23:20:17 -08:00
parent d43f6afdd9
commit 4a5dcd3a4d
4 changed files with 85 additions and 0 deletions

View File

@ -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 {

View File

@ -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
}

View File

@ -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
}

View File

@ -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 {