go-multiaddr/codec.go

194 lines
3.4 KiB
Go
Raw Normal View History

2014-07-03 23:42:24 -07:00
package multiaddr
2014-07-04 11:21:39 -07:00
import (
"bytes"
2014-07-04 11:21:39 -07:00
"fmt"
"strings"
2014-07-03 23:42:24 -07:00
)
2014-09-11 10:47:56 -07:00
func stringToBytes(s string) ([]byte, error) {
2014-10-10 20:40:51 -07:00
// consume trailing slashes
s = strings.TrimRight(s, "/")
var b bytes.Buffer
2014-07-04 11:21:39 -07:00
sp := strings.Split(s, "/")
2014-07-03 23:42:24 -07:00
2014-09-11 10:45:20 -07:00
if sp[0] != "" {
return nil, fmt.Errorf("invalid multiaddr, must begin with /")
}
2014-07-04 11:21:39 -07:00
// consume first empty elem
sp = sp[1:]
2014-07-03 23:42:24 -07:00
2014-07-04 11:21:39 -07:00
for len(sp) > 0 {
name := sp[0]
p := ProtocolWithName(name)
2015-01-09 05:37:02 -08:00
if p.Code == 0 {
2014-07-04 11:21:39 -07:00
return nil, fmt.Errorf("no protocol with name %s", sp[0])
}
_, _ = b.Write(CodeToVarint(p.Code))
2014-11-19 13:01:52 -08:00
sp = sp[1:]
2014-07-03 23:42:24 -07:00
2015-01-17 21:12:54 -08:00
if p.Size == 0 { // no length.
continue
}
if len(sp) < 1 {
return nil, fmt.Errorf("protocol requires address, none given: %s", name)
2015-01-17 21:12:54 -08:00
}
2016-09-12 02:03:41 -04:00
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])
2015-01-17 21:12:54 -08:00
if err != nil {
return nil, fmt.Errorf("failed to parse %s: %s %s", p.Name, sp[0], err)
2014-11-19 13:01:52 -08:00
}
if p.Size < 0 { // varint size.
_, _ = b.Write(CodeToVarint(len(a)))
}
b.Write(a)
2015-01-17 21:12:54 -08:00
sp = sp[1:]
2014-07-04 11:21:39 -07:00
}
return b.Bytes(), nil
2014-07-03 23:42:24 -07:00
}
func validateBytes(b []byte) (err error) {
for len(b) > 0 {
code, n, err := ReadVarintCode(b)
2016-05-04 13:26:50 -07:00
if err != nil {
return err
}
b = b[n:]
p := ProtocolWithCode(code)
if p.Code == 0 {
return fmt.Errorf("no protocol with code %d", code)
}
if p.Size == 0 {
continue
}
2014-07-04 11:21:39 -07:00
n, size, err := sizeForAddr(p, b)
if err != nil {
return err
}
b = b[n:]
2016-05-04 10:51:57 -07:00
if len(b) < size || size < 0 {
return fmt.Errorf("invalid value for size %d", len(b))
}
2016-05-04 10:51:57 -07:00
err = p.Transcoder.ValidateBytes(b[:size])
if err != nil {
return err
}
b = b[size:]
}
return nil
}
2016-05-04 13:26:50 -07:00
func readComponent(b []byte) (int, Component, error) {
var offset int
code, n, err := ReadVarintCode(b)
if err != nil {
return 0, Component{}, err
}
offset += n
2014-07-04 11:21:39 -07:00
p := ProtocolWithCode(code)
if p.Code == 0 {
return 0, Component{}, fmt.Errorf("no protocol with code %d", code)
}
2014-11-19 13:01:52 -08:00
if p.Size == 0 {
return offset, Component{
bytes: b[:offset],
offset: offset,
protocol: p,
}, nil
}
2014-07-04 11:21:39 -07:00
n, size, err := sizeForAddr(p, b[offset:])
if err != nil {
return 0, Component{}, err
}
2015-01-17 21:12:54 -08:00
offset += n
if len(b[offset:]) < size || size < 0 {
return 0, Component{}, fmt.Errorf("invalid value for size %d", len(b[offset:]))
}
return offset + size, Component{
bytes: b[:offset+size],
protocol: p,
offset: offset,
}, nil
}
func bytesToString(b []byte) (ret string, err error) {
var buf strings.Builder
for len(b) > 0 {
n, c, err := readComponent(b)
2015-01-17 21:12:54 -08:00
if err != nil {
return "", err
}
b = b[n:]
c.writeTo(&buf)
2014-07-04 11:21:39 -07:00
}
return buf.String(), nil
2014-07-03 23:42:24 -07:00
}
2014-07-03 23:44:09 -07:00
func sizeForAddr(p Protocol, b []byte) (skip, size int, err error) {
2015-01-20 13:54:05 -08:00
switch {
case p.Size > 0:
return 0, (p.Size / 8), nil
2015-01-20 13:54:05 -08:00
case p.Size == 0:
return 0, 0, nil
2015-01-20 13:54:05 -08:00
default:
size, n, err := ReadVarintCode(b)
if err != nil {
return 0, 0, err
}
return n, size, nil
2015-01-20 13:54:05 -08:00
}
}
func bytesSplit(b []byte) ([][]byte, error) {
var ret [][]byte
for len(b) > 0 {
code, n, err := ReadVarintCode(b)
if err != nil {
return nil, err
2014-11-04 23:20:17 -08:00
}
2014-11-19 13:01:52 -08:00
p := ProtocolWithCode(code)
2015-01-09 05:37:02 -08:00
if p.Code == 0 {
return nil, fmt.Errorf("no protocol with code %d", b[0])
}
n2, size, err := sizeForAddr(p, b[n:])
if err != nil {
return nil, err
2014-11-04 23:20:17 -08:00
}
length := n + n2 + size
2014-11-04 23:20:17 -08:00
ret = append(ret, b[:length])
b = b[length:]
}
return ret, nil
}