From 286ac4557dbfa0abca5e9912080d73d37a4df051 Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Sun, 3 Mar 2024 13:56:48 -0600 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Add=20tools.WriteValue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- models/meta.go | 33 +++---------------------- models/meta_test.go | 2 +- tools/write_buffer.go | 44 ++++++++++++++++++++++++++++++++++ tools/write_buffer_test.go | 49 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 31 deletions(-) create mode 100644 tools/write_buffer.go create mode 100644 tools/write_buffer_test.go diff --git a/models/meta.go b/models/meta.go index c737f95..dba99b2 100644 --- a/models/meta.go +++ b/models/meta.go @@ -2,12 +2,9 @@ package models import ( "bytes" - "encoding/json" "errors" "fmt" "regexp" - "strconv" - "time" "codeberg.org/danjones000/my-log/tools" ) @@ -25,33 +22,9 @@ func (m Meta) MarshalText() ([]byte, error) { buff.WriteRune('@') buff.WriteString(m.Key) buff.WriteRune(' ') - switch v := m.Value.(type) { - default: - return nil, fmt.Errorf("Unknown type %T", v) - case nil: - return []byte{}, nil - case string: - buff.WriteString(v) - case int: - buff.WriteString(strconv.Itoa(v)) - case int64: - buff.WriteString(strconv.FormatInt(v, 10)) - case float64: - buff.WriteString(strconv.FormatFloat(v, 'f', -1, 64)) - case json.Number: - buff.WriteString(v.String()) - case json.RawMessage: - buff.Write(v) - case []byte: - buff.Write(v) - case byte: - buff.WriteByte(v) - case rune: - buff.WriteString(string(v)) - case bool: - buff.WriteString(strconv.FormatBool(v)) - case time.Time: - buff.WriteString(v.Format(time.RFC3339)) + n, err := tools.WriteValue(buff, m.Value) + if n == 0 || err != nil { + return []byte{}, err } return buff.Bytes(), nil diff --git a/models/meta_test.go b/models/meta_test.go index 2dae977..1e0888b 100644 --- a/models/meta_test.go +++ b/models/meta_test.go @@ -40,7 +40,7 @@ func TestMeta(t *testing.T) { {"byte", "byteme", byte(67), "@byteme C", nil, "C"}, {"json-obj", "obj", json.RawMessage(`{"foo":"bar","baz":"quux"}`), `@obj {"foo":"bar","baz":"quux"}`, nil, json.RawMessage(`{"foo":"bar","baz":"quux"}`)}, {"json-arr", "arr", json.RawMessage(`["foo",42,"bar", null,"quux", true]`), `@arr ["foo",42,"bar", null,"quux", true]`, nil, json.RawMessage(`["foo",42,"bar", null,"quux", true]`)}, - {"chan", "nope", make(chan bool), "", errors.New("Unknown type chan bool"), ""}, + {"chan", "nope", make(chan bool), "", errors.New("Unsupported type chan bool"), ""}, {"whitespace-key", "no space", "hi", "", errors.New("whitespace is not allowed in key: no space"), ""}, {"empty-mar", "nope", skipMarshalTest, "", nil, ErrorParsing}, {"no-key-mar", "nope", skipMarshalTest, "nope", nil, ErrorParsing}, diff --git a/tools/write_buffer.go b/tools/write_buffer.go new file mode 100644 index 0000000..e67d219 --- /dev/null +++ b/tools/write_buffer.go @@ -0,0 +1,44 @@ +package tools + +import ( + "bytes" + "encoding/json" + "fmt" + "strconv" + "time" +) + +func WriteValue(buff *bytes.Buffer, val any) (n int, err error) { + switch v := val.(type) { + default: + err = fmt.Errorf("Unsupported type %T", v) + case nil: + return + case string: + return buff.WriteString(v) + case int: + return buff.WriteString(strconv.Itoa(v)) + case int64: + return buff.WriteString(strconv.FormatInt(v, 10)) + case float64: + return buff.WriteString(strconv.FormatFloat(v, 'f', -1, 64)) + case json.Number: + return buff.WriteString(v.String()) + case json.RawMessage: + return buff.Write(v) + case []byte: + return buff.Write(v) + case byte: + err = buff.WriteByte(v) + if err == nil { + n = 1 + } + case rune: + return buff.WriteString(string(v)) + case bool: + return buff.WriteString(strconv.FormatBool(v)) + case time.Time: + return buff.WriteString(v.Format(time.RFC3339)) + } + return +} diff --git a/tools/write_buffer_test.go b/tools/write_buffer_test.go new file mode 100644 index 0000000..1a4a103 --- /dev/null +++ b/tools/write_buffer_test.go @@ -0,0 +1,49 @@ +package tools + +import ( + "bytes" + "encoding/json" + "errors" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestWriteBuffer(t *testing.T) { + when := time.Now() + tests := []struct { + name string + value any + out string + err error + }{ + {"nil", nil, "", nil}, + {"string", "hi", "hi", nil}, + {"bytes", []byte{104, 105}, "hi", nil}, + {"byte", byte(104), "h", nil}, + {"rune", 'h', "h", nil}, + {"int", 42, "42", nil}, + {"int64", int64(42), "42", nil}, + {"float", 42.13, "42.13", nil}, + {"bool", false, "false", nil}, + {"json.Number", json.Number("42.13"), "42.13", nil}, + {"json.RawMessage", json.RawMessage("{}"), "{}", nil}, + {"time", when, when.Format(time.RFC3339), nil}, + {"struct", struct{}{}, "", errors.New("Unsupported type struct {}")}, + } + + for _, tt := range tests { + t.Run(tt.name, getWriteTestRunner(tt.value, tt.out, tt.err)) + } +} + +func getWriteTestRunner(value any, out string, err error) func(*testing.T) { + return func(t *testing.T) { + buff := &bytes.Buffer{} + n, er := WriteValue(buff, value) + assert.Equal(t, len(out), n) + assert.Equal(t, err, er) + assert.Equal(t, out, buff.String()) + } +}