package multiaddr
import (
"bytes"
"fmt"
"strings"
"github.com/multiformats/go-varint"
)
func stringToBytes(s string ) ([]byte , error ) {
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 )
}
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 {
continue
}
if len (sp ) < 1 {
return nil , fmt .Errorf ("failed to parse multiaddr %q: unexpected end of multiaddr" , s )
}
if p .Path {
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 {
_, _ = 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 {
var n int
size , n , err = ReadVarintCode (b [offset :])
if err != nil {
return 0 , nil , err
}
offset += n
} else {
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 {
return bytesRead , nil , fmt .Errorf ("unexpected component after path component" )
}
sawPathComponent = c .protocol .Path
res = append (res , *c )
}
return bytesRead , res , nil
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .