✨ Add Meta with TextMarshaler
This commit is contained in:
parent
c61c783c66
commit
3cfb1ccedb
2 changed files with 106 additions and 0 deletions
|
|
@ -1 +1,53 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Meta struct {
|
||||||
|
Key string
|
||||||
|
Value any
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Meta) MarshalText() ([]byte, error) {
|
||||||
|
if regexp.MustCompile(`\s`).MatchString(m.Key) {
|
||||||
|
return []byte{}, fmt.Errorf("whitespace is now allowed in key: %s", m.Key)
|
||||||
|
}
|
||||||
|
buff := &bytes.Buffer{}
|
||||||
|
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 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))
|
||||||
|
}
|
||||||
|
|
||||||
|
return buff.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
|
||||||
54
models/meta_test.go
Normal file
54
models/meta_test.go
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Type assertions
|
||||||
|
var _ encoding.TextMarshaler = Meta{}
|
||||||
|
|
||||||
|
func TestMeta(t *testing.T) {
|
||||||
|
when := time.Now()
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
key string
|
||||||
|
value any
|
||||||
|
out string
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{"int", "num", 42, "@num 42", nil},
|
||||||
|
{"float", "num", 42.13, "@num 42.13", nil},
|
||||||
|
{"string", "word", "hello", "@word hello", nil},
|
||||||
|
{"json number", "num", json.Number("42.13"), "@num 42.13", nil},
|
||||||
|
{"true", "b", true, "@b true", nil},
|
||||||
|
{"false", "b", false, "@b false", nil},
|
||||||
|
{"nil", "n", nil, "", nil},
|
||||||
|
{"time", "when", when, "@when " + when.Format(time.RFC3339), nil},
|
||||||
|
{"rune", "char", '@', "@char @", nil},
|
||||||
|
{"bytes", "byteme", []byte("yo"), "@byteme yo", nil},
|
||||||
|
{"byte", "byteme", byte(67), "@byteme C", nil},
|
||||||
|
{"json-obj", "obj", json.RawMessage(`{"foo":"bar","baz":"quux"}`), `@obj {"foo":"bar","baz":"quux"}`, nil},
|
||||||
|
{"json-arr", "arr", json.RawMessage(`["foo",42,"bar", null,"quux", true]`), `@arr ["foo",42,"bar", null,"quux", true]`, nil},
|
||||||
|
{"chan", "nope", make(chan bool), "", errors.New("Unknown type chan bool")},
|
||||||
|
{"whitespace", "no space", "hi", "", errors.New("whitespace is now allowed in key: no space")},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, getMetaTestRunner(tt.key, tt.value, tt.out, tt.err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMetaTestRunner(key string, value any, out string, err error) func(*testing.T) {
|
||||||
|
return func(t *testing.T) {
|
||||||
|
st := Meta{key, value}
|
||||||
|
o, e := st.MarshalText()
|
||||||
|
assert.Equal(t, out, string(o))
|
||||||
|
assert.Equal(t, err, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue