mirror of
https://github.com/logos-messaging/go-multiaddr.git
synced 2026-01-02 13:03:11 +00:00
stop copying when calling Bytes
This is a huge performance hit. Really, we just need to tell users not to modify the result. Also, get rid of an unnecessary pointer indirection (no api change).
This commit is contained in:
parent
fe1c46f8be
commit
61e31ed48b
@ -18,6 +18,8 @@ type Multiaddr interface {
|
||||
Equal(Multiaddr) bool
|
||||
|
||||
// Bytes returns the []byte representation of this Multiaddr
|
||||
//
|
||||
// This function may expose immutable, internal state. Do not modify.
|
||||
Bytes() []byte
|
||||
|
||||
// String returns the string representation of this Multiaddr
|
||||
|
||||
31
multiaddr.go
31
multiaddr.go
@ -24,7 +24,7 @@ func NewMultiaddr(s string) (a Multiaddr, err error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &multiaddr{bytes: b}, nil
|
||||
return multiaddr{bytes: b}, nil
|
||||
}
|
||||
|
||||
// NewMultiaddrBytes initializes a Multiaddr from a byte representation.
|
||||
@ -41,34 +41,33 @@ func NewMultiaddrBytes(b []byte) (a Multiaddr, err error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &multiaddr{bytes: b}, nil
|
||||
return multiaddr{bytes: b}, nil
|
||||
}
|
||||
|
||||
// Equal tests whether two multiaddrs are equal
|
||||
func (m *multiaddr) Equal(m2 Multiaddr) bool {
|
||||
func (m multiaddr) Equal(m2 Multiaddr) bool {
|
||||
return bytes.Equal(m.bytes, m2.Bytes())
|
||||
}
|
||||
|
||||
// Bytes returns the []byte representation of this Multiaddr
|
||||
func (m *multiaddr) Bytes() []byte {
|
||||
// consider returning copy to prevent changing underneath us?
|
||||
cpy := make([]byte, len(m.bytes))
|
||||
copy(cpy, m.bytes)
|
||||
return cpy
|
||||
//
|
||||
// Do not modify the returned buffer, it may be shared.
|
||||
func (m multiaddr) Bytes() []byte {
|
||||
return m.bytes
|
||||
}
|
||||
|
||||
// String returns the string representation of a Multiaddr
|
||||
func (m *multiaddr) String() string {
|
||||
func (m multiaddr) String() string {
|
||||
s, err := bytesToString(m.bytes)
|
||||
if err != nil {
|
||||
panic("multiaddr failed to convert back to string. corrupted?")
|
||||
panic(fmt.Errorf("multiaddr failed to convert back to string. corrupted? %s", err))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Protocols returns the list of protocols this Multiaddr has.
|
||||
// will panic in case we access bytes incorrectly.
|
||||
func (m *multiaddr) Protocols() []Protocol {
|
||||
func (m multiaddr) Protocols() []Protocol {
|
||||
ps := make([]Protocol, 0, 8)
|
||||
b := m.bytes
|
||||
for len(b) > 0 {
|
||||
@ -97,18 +96,18 @@ func (m *multiaddr) Protocols() []Protocol {
|
||||
}
|
||||
|
||||
// Encapsulate wraps a given Multiaddr, returning the resulting joined Multiaddr
|
||||
func (m *multiaddr) Encapsulate(o Multiaddr) Multiaddr {
|
||||
func (m multiaddr) Encapsulate(o Multiaddr) Multiaddr {
|
||||
mb := m.bytes
|
||||
ob := o.Bytes()
|
||||
|
||||
b := make([]byte, len(mb)+len(ob))
|
||||
copy(b, mb)
|
||||
copy(b[len(mb):], ob)
|
||||
return &multiaddr{bytes: b}
|
||||
return multiaddr{bytes: b}
|
||||
}
|
||||
|
||||
// Decapsulate unwraps Multiaddr up until the given Multiaddr is found.
|
||||
func (m *multiaddr) Decapsulate(o Multiaddr) Multiaddr {
|
||||
func (m multiaddr) Decapsulate(o Multiaddr) Multiaddr {
|
||||
s1 := m.String()
|
||||
s2 := o.String()
|
||||
i := strings.LastIndex(s1, s2)
|
||||
@ -116,7 +115,7 @@ func (m *multiaddr) Decapsulate(o Multiaddr) Multiaddr {
|
||||
// if multiaddr not contained, returns a copy.
|
||||
cpy := make([]byte, len(m.bytes))
|
||||
copy(cpy, m.bytes)
|
||||
return &multiaddr{bytes: cpy}
|
||||
return multiaddr{bytes: cpy}
|
||||
}
|
||||
|
||||
ma, err := NewMultiaddr(s1[:i])
|
||||
@ -128,7 +127,7 @@ func (m *multiaddr) Decapsulate(o Multiaddr) Multiaddr {
|
||||
|
||||
var ErrProtocolNotFound = fmt.Errorf("protocol not found in multiaddr")
|
||||
|
||||
func (m *multiaddr) ValueForProtocol(code int) (string, error) {
|
||||
func (m multiaddr) ValueForProtocol(code int) (string, error) {
|
||||
for _, sub := range Split(m) {
|
||||
p := sub.Protocols()[0]
|
||||
if p.Code == code {
|
||||
|
||||
@ -229,12 +229,6 @@ func TestBytesSplitAndJoin(t *testing.T) {
|
||||
t.Errorf("joined components failed: %s != %s", m, joined)
|
||||
}
|
||||
|
||||
// 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])
|
||||
|
||||
6
util.go
6
util.go
@ -11,7 +11,7 @@ func Split(m Multiaddr) []Multiaddr {
|
||||
|
||||
addrs := make([]Multiaddr, len(split))
|
||||
for i, addr := range split {
|
||||
addrs[i] = &multiaddr{bytes: addr}
|
||||
addrs[i] = multiaddr{bytes: addr}
|
||||
}
|
||||
return addrs
|
||||
}
|
||||
@ -34,7 +34,7 @@ func Join(ms ...Multiaddr) Multiaddr {
|
||||
bidx++
|
||||
}
|
||||
}
|
||||
return &multiaddr{bytes: b}
|
||||
return multiaddr{bytes: b}
|
||||
}
|
||||
|
||||
// Cast re-casts a byte slice as a multiaddr. will panic if it fails to parse.
|
||||
@ -43,7 +43,7 @@ func Cast(b []byte) Multiaddr {
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("multiaddr failed to parse: %s", err))
|
||||
}
|
||||
return &multiaddr{bytes: b}
|
||||
return multiaddr{bytes: b}
|
||||
}
|
||||
|
||||
// StringCast like Cast, but parses a string. Will also panic if it fails to parse.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user