mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-12-26 16:45:18 +00:00
212 lines
3.9 KiB
Go
212 lines
3.9 KiB
Go
|
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:]
|
||
|
}
|
||
|
}
|