Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Megular Expressions #263

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions component.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@ func (c *Component) Protocol() Protocol {
return *c.protocol
}

func (c *Component) Code() int {
if c == nil {
return 0
}
return c.Protocol().Code
}

func (c *Component) RawValue() []byte {
if c == nil {
return nil
Expand Down
54 changes: 54 additions & 0 deletions meg_capturers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package multiaddr

import (
"encoding/binary"
"fmt"
"net/netip"

"github.com/multiformats/go-multiaddr/x/meg"
)

func CaptureAddrPort(network *string, ipPort *netip.AddrPort) (capturePattern meg.Pattern) {
var ipOnly netip.Addr
capturePort := func(s meg.Matchable) error {
switch s.Code() {
case P_UDP:
*network = "udp"
case P_TCP:
*network = "tcp"
default:
return fmt.Errorf("invalid network: %s", s.Value())
}

port := binary.BigEndian.Uint16(s.RawValue())
*ipPort = netip.AddrPortFrom(ipOnly, port)
return nil
}

pattern := meg.Cat(
meg.Or(
meg.CaptureWithF(P_IP4, func(s meg.Matchable) error {
var ok bool
ipOnly, ok = netip.AddrFromSlice(s.RawValue())
if !ok {
return fmt.Errorf("invalid ip4 address: %s", s.Value())
}
return nil
}),
meg.CaptureWithF(P_IP6, func(s meg.Matchable) error {
var ok bool
ipOnly, ok = netip.AddrFromSlice(s.RawValue())
if !ok {
return fmt.Errorf("invalid ip6 address: %s", s.Value())
}
return nil
}),
),
meg.Or(
meg.CaptureWithF(P_UDP, capturePort),
meg.CaptureWithF(P_TCP, capturePort),
),
)

return pattern
}
72 changes: 72 additions & 0 deletions meg_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package multiaddr

import (
"net/netip"
"testing"

"github.com/multiformats/go-multiaddr/x/meg"
)

func TestMatchAndCaptureMultiaddr(t *testing.T) {
m := StringCast("/ip4/1.2.3.4/udp/8231/quic-v1/webtransport/certhash/b2uaraocy6yrdblb4sfptaddgimjmmpy/certhash/zQmbWTwYGcmdyK9CYfNBcfs9nhZs17a6FQ4Y8oea278xx41")

var udpPort string
var certhashes []string
found, _ := m.Match(
meg.Or(
meg.Val(P_IP4),
meg.Val(P_IP6),
),
meg.CaptureStringVal(P_UDP, &udpPort),
meg.Val(P_QUIC_V1),
meg.Val(P_WEBTRANSPORT),
meg.CaptureZeroOrMoreStringVals(P_CERTHASH, &certhashes),
)
if !found {
t.Fatal("failed to match")
}
if udpPort != "8231" {
t.Fatal("unexpected value")
}

if len(certhashes) != 2 {
t.Fatal("Didn't capture all certhashes")
}

{
m, c := SplitLast(m)
if c.Value() != certhashes[1] {
t.Fatal("unexpected value. Expected", c.RawValue(), "but got", []byte(certhashes[1]))
}
_, c = SplitLast(m)
if c.Value() != certhashes[0] {
t.Fatal("unexpected value. Expected", c.RawValue(), "but got", []byte(certhashes[0]))
}
}
}

func TestCaptureAddrPort(t *testing.T) {
m := StringCast("/ip4/1.2.3.4/udp/8231/quic-v1/webtransport")
var addrPort netip.AddrPort
var network string

found, err := m.Match(
CaptureAddrPort(&network, &addrPort),
meg.ZeroOrMore(meg.Any),
)
if err != nil {
t.Fatal("error", err)
}
if !found {
t.Fatal("failed to match")
}
if !addrPort.IsValid() {
t.Fatal("failed to capture addrPort")
}
if network != "udp" {
t.Fatal("unexpected network", network)
}
if addrPort.String() != "1.2.3.4:8231" {
t.Fatal("unexpected ipPort", addrPort)
}
}
7 changes: 7 additions & 0 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package multiaddr

import (
"fmt"

"github.com/multiformats/go-multiaddr/x/meg"
)

// Split returns the sub-address portions of a multiaddr.
Expand Down Expand Up @@ -120,3 +122,8 @@ func ForEach(m Multiaddr, cb func(c Component) bool) {
}
}
}

func (m Multiaddr) Match(p ...meg.Pattern) (bool, error) {
matcher := meg.PatternToMatcher(p...)
return meg.Match(matcher, m, func(c *Component) meg.Matchable { return c })
}
Loading