From d96900ba17528d8e3553d48608a47bfd1710091e Mon Sep 17 00:00:00 2001 From: Mark Puha Date: Thu, 5 Jun 2025 20:16:00 +0200 Subject: [PATCH] feat: parser error cases & generator skeleton --- device/internal/junk-tag/generator.go | 14 ++++ device/internal/junk-tag/parser.go | 87 +++++++++++++++++++++++++ device/internal/junk-tag/parser_test.go | 60 +++++++++++++++++ go.mod | 4 ++ go.sum | 10 +++ 5 files changed, 175 insertions(+) create mode 100644 device/internal/junk-tag/generator.go create mode 100644 device/internal/junk-tag/parser.go create mode 100644 device/internal/junk-tag/parser_test.go diff --git a/device/internal/junk-tag/generator.go b/device/internal/junk-tag/generator.go new file mode 100644 index 0000000..ca96dee --- /dev/null +++ b/device/internal/junk-tag/generator.go @@ -0,0 +1,14 @@ +package junktag + +type Generator interface { + Generate() []byte +} + +type newGenerator func(string) (Generator, error) + +type BytesGenerator struct { +} + +func (b *BytesGenerator) Generate() []byte { + return nil +} diff --git a/device/internal/junk-tag/parser.go b/device/internal/junk-tag/parser.go new file mode 100644 index 0000000..0160a4e --- /dev/null +++ b/device/internal/junk-tag/parser.go @@ -0,0 +1,87 @@ +package junktag + +import ( + "fmt" + "regexp" + "strings" +) + +type Enum string + +const ( + EnumBytes Enum = "b" + EnumCounter Enum = "c" + EnumTimestamp Enum = "t" + EnumRandomBytes Enum = "r" + EnumWaitTimeout Enum = "wt" + EnumWaitResponse Enum = "wr" +) + +var validEnum = map[Enum]newGenerator{ + EnumBytes: func(s string) (Generator, error) { return &BytesGenerator{}, nil }, + EnumCounter: func(s string) (Generator, error) { return &BytesGenerator{}, nil }, + EnumTimestamp: func(s string) (Generator, error) { return &BytesGenerator{}, nil }, + EnumRandomBytes: func(s string) (Generator, error) { return &BytesGenerator{}, nil }, + EnumWaitTimeout: func(s string) (Generator, error) { return &BytesGenerator{}, nil }, + EnumWaitResponse: func(s string) (Generator, error) { return &BytesGenerator{}, nil }, +} + +type Foo struct { + x []Generator +} + +type Tag struct { + Name Enum + Param string +} + +func parseTags(input string) ([]Tag, error) { + // Regular expression to match + re := regexp.MustCompile(`([a-zA-Z]+)(?:\s+([^>]+))?>`) + + matches := re.FindAllStringSubmatch(input, -1) + tags := make([]Tag, 0, len(matches)) + + for _, match := range matches { + tag := Tag{ + Name: Enum(match[1]), + } + if len(match) > 2 && match[2] != "" { + tag.Param = strings.TrimSpace(match[2]) + } + tags = append(tags, tag) + } + + return tags, nil +} + +func Parse(input string) (Foo, error) { + inputSlice := strings.Split(input, "<") + fmt.Printf("%v\n", inputSlice) + if len(inputSlice) <= 1 { + return Foo{}, fmt.Errorf("empty input: %s", input) + } + + for _, inputParam := range inputSlice[1:] { + if len(inputParam) == 1 { + return Foo{}, fmt.Errorf("empty tag in input: %s", inputSlice) + } else if strings.Count(inputParam, ">") != 1 { + return Foo{}, fmt.Errorf("ill formated input: %s", input) + } + + tags, _ := parseTags(inputParam) + for _, tag := range tags { + fmt.Printf("Tag: %s, Param: %s\n", tag.Name, tag.Param) + gen, ok := validEnum[tag.Name] + if !ok { + return Foo{}, fmt.Errorf("invalid tag") + } + _, err := gen(tag.Param) + if err != nil { + return Foo{}, fmt.Errorf("") + } + } + } + + return Foo{}, nil +} diff --git a/device/internal/junk-tag/parser_test.go b/device/internal/junk-tag/parser_test.go new file mode 100644 index 0000000..6c1f33b --- /dev/null +++ b/device/internal/junk-tag/parser_test.go @@ -0,0 +1,60 @@ +package junktag + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParse(t *testing.T) { + type args struct { + input string + } + tests := []struct { + name string + args args + wantErr error + }{ + { + name: "empty", + args: args{input: ""}, + wantErr: fmt.Errorf("ill formated input"), + }, + { + name: "extra >", + args: args{input: ">"}, + wantErr: fmt.Errorf("ill formated input"), + }, + { + name: "extra <", + args: args{input: "<"}, + wantErr: fmt.Errorf("ill formated input"), + }, + { + name: "empty <>", + args: args{input: "<>"}, + wantErr: fmt.Errorf("empty tag in input"), + }, + { + name: "invalid tag", + args: args{input: ""}, + wantErr: fmt.Errorf("invalid tag"), + }, + { + name: "valid", + args: args{input: ""}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := Parse(tt.args.input) + + // TODO: ErrorAs doesn't work as you think + // if tt.wantErr != nil { + require.ErrorAs(t, err, &tt.wantErr) + // return + // } + }) + } +} diff --git a/go.mod b/go.mod index 608969f..c150a4b 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/amnezia-vpn/amneziawg-go go 1.24 require ( + github.com/stretchr/testify v1.10.0 github.com/tevino/abool/v2 v2.1.0 golang.org/x/crypto v0.36.0 golang.org/x/net v0.37.0 @@ -12,6 +13,9 @@ require ( ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/google/btree v1.1.3 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/time v0.9.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 497f949..ec3fa7f 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,13 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tevino/abool/v2 v2.1.0 h1:7w+Vf9f/5gmKT4m4qkayb33/92M+Um45F2BkHOR+L/c= github.com/tevino/abool/v2 v2.1.0/go.mod h1:+Lmlqk6bHDWHqN1cbxqhwEAwMPXgc8I1SDEamtseuXY= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= @@ -16,5 +22,9 @@ golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gvisor.dev/gvisor v0.0.0-20250130013005-04f9204697c6 h1:6B7MdW3OEbJqOMr7cEYU9bkzvCjUBX/JlXk12xcANuQ= gvisor.dev/gvisor v0.0.0-20250130013005-04f9204697c6/go.mod h1:5DMfjtclAbTIjbXqO1qCe2K5GKKxWz2JHvCChuTcJEM=