status-go/vendor/github.com/whyrusleeping/mafmt/patterns.go

134 lines
2.5 KiB
Go

package mafmt
import (
"strings"
ma "github.com/multiformats/go-multiaddr"
)
// Define IP as either ipv4 or ipv6
var IP = Or(Base(ma.P_IP4), Base(ma.P_IP6))
// Define TCP as 'tcp' on top of either ipv4 or ipv6
var TCP = And(IP, Base(ma.P_TCP))
// Define UDP as 'udp' on top of either ipv4 or ipv6
var UDP = And(IP, Base(ma.P_UDP))
// Define UTP as 'utp' on top of udp (on top of ipv4 or ipv6)
var UTP = And(UDP, Base(ma.P_UTP))
// Define QUIC as 'quic' on top of udp (on top of ipv4 or ipv6)
var QUIC = And(UDP, Base(ma.P_QUIC))
// Define unreliable transport as udp
var Unreliable = Or(UDP)
// Now define a Reliable transport as either tcp or utp or quic
var Reliable = Or(TCP, UTP, QUIC)
// IPFS can run over any reliable underlying transport protocol
var IPFS = And(Reliable, Base(ma.P_IPFS))
const (
or = iota
and = iota
)
func And(ps ...Pattern) Pattern {
return &pattern{
Op: and,
Args: ps,
}
}
func Or(ps ...Pattern) Pattern {
return &pattern{
Op: or,
Args: ps,
}
}
type Pattern interface {
Matches(ma.Multiaddr) bool
partialMatch([]ma.Protocol) (bool, []ma.Protocol)
String() string
}
type pattern struct {
Args []Pattern
Op int
}
func (ptrn *pattern) Matches(a ma.Multiaddr) bool {
ok, rem := ptrn.partialMatch(a.Protocols())
return ok && len(rem) == 0
}
func (ptrn *pattern) partialMatch(pcs []ma.Protocol) (bool, []ma.Protocol) {
switch ptrn.Op {
case or:
for _, a := range ptrn.Args {
ok, rem := a.partialMatch(pcs)
if ok {
return true, rem
}
}
return false, nil
case and:
if len(pcs) < len(ptrn.Args) {
return false, nil
}
for i := 0; i < len(ptrn.Args); i++ {
ok, rem := ptrn.Args[i].partialMatch(pcs)
if !ok {
return false, nil
}
pcs = rem
}
return true, pcs
default:
panic("unrecognized pattern operand")
}
}
func (ptrn *pattern) String() string {
var sub []string
for _, a := range ptrn.Args {
sub = append(sub, a.String())
}
switch ptrn.Op {
case and:
return strings.Join(sub, "/")
case or:
return "{" + strings.Join(sub, "|") + "}"
default:
panic("unrecognized pattern op!")
}
}
type Base int
func (p Base) Matches(a ma.Multiaddr) bool {
pcs := a.Protocols()
return pcs[0].Code == int(p) && len(pcs) == 1
}
func (p Base) partialMatch(pcs []ma.Protocol) (bool, []ma.Protocol) {
if len(pcs) == 0 {
return false, nil
}
if pcs[0].Code == int(p) {
return true, pcs[1:]
}
return false, nil
}
func (p Base) String() string {
return ma.ProtocolWithCode(int(p)).Name
}