✨ 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 | ||||
| 
 | ||||
| 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