aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/cpe/avstring.go54
-rw-r--r--internal/cpe/avstring_test.go95
-rw-r--r--internal/cpe/avstringtype_string.go25
3 files changed, 174 insertions, 0 deletions
diff --git a/internal/cpe/avstring.go b/internal/cpe/avstring.go
new file mode 100644
index 0000000..46e16cf
--- /dev/null
+++ b/internal/cpe/avstring.go
@@ -0,0 +1,54 @@
+package cpe
+
+//go:generate stringer -linecomment -type=AvStringType
+
+import (
+ "fmt"
+)
+
+// type of avstring.
+type AvStringType byte
+
+const (
+ AnyString AvStringType = iota // any
+ NaString // na
+ ValString // val
+)
+
+// String value (NISTIR 7695, CPE 2.3 spec, Figure 6-3)
+type AvString struct {
+ Type AvStringType // value type
+ Val string // value
+}
+
+// token type to avstring type map
+var avTypes = map[tokenType]AvStringType {
+ anyToken: AnyString,
+ naToken: NaString,
+ valToken: ValString,
+}
+
+// create new AvString from token.
+func newAvString(t token) (AvString, error) {
+ if at, ok := avTypes[t.Type]; ok {
+ return AvString { at, t.Val }, nil
+ } else {
+ err := fmt.Errorf("invalid token type: 0x%02x", byte(t.Type))
+ return AvString { 0, "" }, err
+ }
+}
+
+// Serialize as string.
+func (s AvString) String() string {
+ switch s.Type {
+ case AnyString:
+ return "*"
+ case NaString:
+ return "-"
+ case ValString:
+ return s.Val
+ default:
+ // not sure what to return here
+ return ""
+ }
+}
diff --git a/internal/cpe/avstring_test.go b/internal/cpe/avstring_test.go
new file mode 100644
index 0000000..8cbb14b
--- /dev/null
+++ b/internal/cpe/avstring_test.go
@@ -0,0 +1,95 @@
+package cpe
+
+import (
+ "testing"
+)
+
+func TestNewAvString(t *testing.T) {
+ passTests := []struct {
+ name string
+ val token
+ exp AvString
+ } {
+ { "any", token { Type: anyToken }, AvString { Type: AnyString } },
+ { "na", token { Type: naToken }, AvString { Type: NaString } },
+ { "empty", token { Type: valToken }, AvString { ValString, "" } },
+ { "foo", token { valToken, "foo" }, AvString { ValString, "foo" } },
+ }
+
+ for _, test := range(passTests) {
+ t.Run(test.name, func(t *testing.T) {
+ got, err := newAvString(test.val)
+ if err != nil {
+ t.Error(err)
+ } else if got.Type != test.exp.Type {
+ t.Errorf("token: got %s, exp %s", got.Type, test.exp.Type)
+ } else if got.Type == ValString && got.Val != test.exp.Val {
+ t.Errorf("value: got \"%s\", exp \"%s\"", got.Val, test.exp.Val)
+ }
+ })
+ }
+
+ failTests := []struct {
+ name string
+ val token
+ exp string
+ } {{
+ name: "invalid token",
+ val: token { Type: tokenType(127), Val: "foo" },
+ exp: "invalid token type: 0x7f",
+ }}
+
+ for _, test := range(failTests) {
+ t.Run(test.name, func(t *testing.T) {
+ got, err := newAvString(test.val)
+ if err == nil {
+ t.Errorf("got %v, exp error", got)
+ } else if err.Error() != test.exp {
+ t.Errorf("got \"%s\", exp \"%s\"", err.Error(), test.exp)
+ }
+ })
+ }
+}
+
+func TestAvStringString(t *testing.T) {
+ tests := []struct {
+ name string
+ val AvString
+ exp string
+ } {
+ { "any", AvString { AnyString, "" }, "*" },
+ { "na", AvString { NaString, "" }, "-" },
+ { "foo", AvString { ValString, "foo" }, "foo" },
+ { "junk", AvString { AvStringType(255), "foo" }, "" },
+ }
+
+ for _, test := range(tests) {
+ t.Run(test.name, func(t *testing.T) {
+ got := test.val.String()
+ if got != test.exp {
+ t.Errorf("value: got \"%s\", exp \"%s\"", got, test.exp)
+ }
+ })
+ }
+}
+
+func TestAvStringTypeString(t *testing.T) {
+ tests := []struct {
+ val AvStringType
+ exp string
+ } {
+ { AnyString, "any" },
+ { NaString, "na" },
+ { ValString, "val" },
+ { AvStringType(255), "AvStringType(255)" },
+ }
+
+ for _, test := range(tests) {
+ t.Run(test.exp, func(t *testing.T) {
+ got := test.val.String()
+ if got != test.exp {
+ t.Errorf("got \"%s\", exp \"%s\"", got, test.exp)
+ }
+ })
+ }
+}
diff --git a/internal/cpe/avstringtype_string.go b/internal/cpe/avstringtype_string.go
new file mode 100644
index 0000000..6fb88e1
--- /dev/null
+++ b/internal/cpe/avstringtype_string.go
@@ -0,0 +1,25 @@
+// Code generated by "stringer -linecomment -type=AvStringType"; DO NOT EDIT.
+
+package cpe
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[AnyString-0]
+ _ = x[NaString-1]
+ _ = x[ValString-2]
+}
+
+const _AvStringType_name = "anynaval"
+
+var _AvStringType_index = [...]uint8{0, 3, 5, 8}
+
+func (i AvStringType) String() string {
+ if i >= AvStringType(len(_AvStringType_index)-1) {
+ return "AvStringType(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _AvStringType_name[_AvStringType_index[i]:_AvStringType_index[i+1]]
+}