ceremonyclient/go-multiaddr/util.go

212 lines
3.9 KiB
Go
Raw Normal View History

2024-10-12 18:48:25 +00:00
package multiaddr
import "fmt"
// Split returns the sub-address portions of a multiaddr.
func Split(m Multiaddr) []Multiaddr {
if _, ok := m.(*Component); ok {
return []Multiaddr{m}
}
var addrs []Multiaddr
var err error
ForEach(m, func(c Component, e error) bool {
if e != nil {
err = e
return false
}
addrs = append(addrs, &c)
return true
})
if err != nil {
return []Multiaddr{}
}
return addrs
}
// Join returns a combination of addresses.
func Join(ms ...Multiaddr) Multiaddr {
switch len(ms) {
case 0:
// empty multiaddr, unfortunately, we have callers that rely on
// this contract.
return &multiaddr{}
case 1:
return ms[0]
}
length := 0
for _, m := range ms {
if m == nil {
continue
}
length += len(m.Bytes())
}
bidx := 0
b := make([]byte, length)
if length == 0 {
return nil
}
for _, mb := range ms {
if mb == nil {
continue
}
bidx += copy(b[bidx:], mb.Bytes())
}
if length == 0 {
return nil
}
return &multiaddr{bytes: b}
}
// Cast re-casts a byte slice as a multiaddr.
func Cast(b []byte) (Multiaddr, error) {
m, err := NewMultiaddrBytes(b)
if err != nil {
return nil, fmt.Errorf("multiaddr failed to parse: %s", err)
}
return m, nil
}
// StringCast like Cast, but parses a string.
func StringCast(s string) (Multiaddr, error) {
m, err := NewMultiaddr(s)
if err != nil {
return nil, fmt.Errorf("multiaddr failed to parse: %s", err)
}
return m, nil
}
// SplitFirst returns the first component and the rest of the multiaddr.
func SplitFirst(m Multiaddr) (*Component, Multiaddr, error) {
if m == nil {
return nil, nil, nil
}
// Shortcut if we already have a component
if c, ok := m.(*Component); ok {
return c, nil, nil
}
b := m.Bytes()
if len(b) == 0 {
return nil, nil, nil
}
n, c, err := readComponent(b)
if err != nil {
return nil, nil, err
}
if len(b) == n {
return &c, nil, nil
}
return &c, &multiaddr{b[n:]}, nil
}
// SplitLast returns the rest of the multiaddr and the last component.
func SplitLast(m Multiaddr) (Multiaddr, *Component, error) {
if m == nil {
return nil, nil, nil
}
// Shortcut if we already have a component
if c, ok := m.(*Component); ok {
return nil, c, nil
}
b := m.Bytes()
if len(b) == 0 {
return nil, nil, nil
}
var (
c Component
err error
offset int
)
for {
var n int
n, c, err = readComponent(b[offset:])
if err != nil {
return nil, nil, err
}
if len(b) == n+offset {
// Reached end
if offset == 0 {
// Only one component
return nil, &c, nil
}
return &multiaddr{b[:offset]}, &c, nil
}
offset += n
}
}
// SplitFunc splits the multiaddr when the callback first returns true. The
// component on which the callback first returns will be included in the
// *second* multiaddr.
func SplitFunc(m Multiaddr, cb func(Component) bool) (Multiaddr, Multiaddr, error) {
if m == nil {
return nil, nil, nil
}
// Shortcut if we already have a component
if c, ok := m.(*Component); ok {
if cb(*c) {
return nil, m, nil
}
return m, nil, nil
}
b := m.Bytes()
if len(b) == 0 {
return nil, nil, nil
}
var (
c Component
err error
offset int
)
for offset < len(b) {
var n int
n, c, err = readComponent(b[offset:])
if err != nil {
return nil, nil, err
}
if cb(c) {
break
}
offset += n
}
switch offset {
case 0:
return nil, m, nil
case len(b):
return m, nil, nil
default:
return &multiaddr{b[:offset]}, &multiaddr{b[offset:]}, nil
}
}
// ForEach walks over the multiaddr, component by component.
//
// This function iterates over components *by value* to avoid allocating.
// Return true to continue iteration, false to stop.
func ForEach(m Multiaddr, cb func(c Component, err error) bool) {
if m == nil {
return
}
// Shortcut if we already have a component
if c, ok := m.(*Component); ok {
cb(*c, nil)
return
}
b := m.Bytes()
for len(b) > 0 {
n, c, err := readComponent(b)
if !cb(c, err) {
return
}
b = b[n:]
}
}