ceremonyclient/go-multiaddr/codec.go
Cassandra Heart dbd95bd9e9
v2.1.0 (#439)
* v2.1.0 [omit consensus and adjacent] - this commit will be amended with the full release after the file copy is complete

* 2.1.0 main node rollup
2025-09-30 02:48:15 -05:00

158 lines
3.3 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package multiaddr
import (
"bytes"
"fmt"
"strings"
"github.com/multiformats/go-varint"
)
func stringToBytes(s string) ([]byte, error) {
// consume trailing slashes
s = strings.TrimRight(s, "/")
var b bytes.Buffer
sp := strings.Split(s, "/")
if sp[0] != "" {
return nil, fmt.Errorf("failed to parse multiaddr %q: must begin with /", s)
}
// consume first empty elem
sp = sp[1:]
if len(sp) == 0 {
return nil, fmt.Errorf("failed to parse multiaddr %q: empty multiaddr", s)
}
for len(sp) > 0 {
name := sp[0]
p := ProtocolWithName(name)
if p.Code == 0 {
return nil, fmt.Errorf("failed to parse multiaddr %q: unknown protocol %s", s, sp[0])
}
_, _ = b.Write(p.VCode)
sp = sp[1:]
if p.Size == 0 { // no length.
continue
}
if len(sp) < 1 {
return nil, fmt.Errorf("failed to parse multiaddr %q: unexpected end of multiaddr", s)
}
if p.Path {
// it's a path protocol (terminal).
// consume the rest of the address as the next component.
sp = []string{"/" + strings.Join(sp, "/")}
}
a, err := p.Transcoder.StringToBytes(sp[0])
if err != nil {
return nil, fmt.Errorf("failed to parse multiaddr %q: invalid value %q for protocol %s: %s", s, sp[0], p.Name, err)
}
err = p.Transcoder.ValidateBytes(a)
if err != nil {
return nil, fmt.Errorf("failed to validate multiaddr %q: invalid value %q for protocol %s: %w", s, sp[0], p.Name, err)
}
if p.Size < 0 { // varint size.
_, _ = b.Write(varint.ToUvarint(uint64(len(a))))
}
b.Write(a)
sp = sp[1:]
}
return b.Bytes(), nil
}
func readComponent(b []byte) (int, *Component, error) {
var offset int
code, n, err := ReadVarintCode(b)
if err != nil {
return 0, nil, err
}
offset += n
p := ProtocolWithCode(code)
if p.Code == 0 {
return 0, nil, fmt.Errorf("no protocol with code %d", code)
}
pPtr := protocolPtrByCode[code]
if pPtr == nil {
return 0, nil, fmt.Errorf("no protocol with code %d", code)
}
if p.Size == 0 {
c := &Component{
bytes: string(b[:offset]),
valueStartIdx: offset,
protocol: pPtr,
}
err := validateComponent(c)
if err != nil {
return 0, nil, err
}
return offset, c, nil
}
var size int
if p.Size < 0 {
// varint
var n int
size, n, err = ReadVarintCode(b[offset:])
if err != nil {
return 0, nil, err
}
offset += n
} else {
// Size is in bits, but we operate on bytes
size = p.Size / 8
}
if len(b[offset:]) < size || size <= 0 {
return 0, nil, fmt.Errorf("invalid value for size %d", len(b[offset:]))
}
c := &Component{
bytes: string(b[:offset+size]),
protocol: pPtr,
valueStartIdx: offset,
}
err = validateComponent(c)
if err != nil {
return 0, nil, err
}
return offset + size, c, err
}
func readMultiaddr(b []byte) (int, Multiaddr, error) {
if len(b) == 0 {
return 0, nil, fmt.Errorf("empty multiaddr")
}
var res Multiaddr
bytesRead := 0
sawPathComponent := false
for len(b) > 0 {
n, c, err := readComponent(b)
if err != nil {
return 0, nil, err
}
b = b[n:]
bytesRead += n
if sawPathComponent {
// It is an error to have another component after a path component.
return bytesRead, nil, fmt.Errorf("unexpected component after path component")
}
sawPathComponent = c.protocol.Path
res = append(res, *c)
}
return bytesRead, res, nil
}