Meta implements TextUnmarshaler

This commit is contained in:
Dan Jones 2024-01-27 16:07:27 -06:00
commit 875ca7e33d
2 changed files with 120 additions and 26 deletions

View file

@ -3,9 +3,11 @@ package models
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"regexp"
"strconv"
"strings"
"time"
)
@ -16,7 +18,7 @@ type Meta struct {
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)
return []byte{}, fmt.Errorf("whitespace is not allowed in key: %s", m.Key)
}
buff := &bytes.Buffer{}
buff.WriteRune('@')
@ -51,3 +53,51 @@ func (m Meta) MarshalText() ([]byte, error) {
return buff.Bytes(), nil
}
func (m *Meta) UnmarshalText(in []byte) error {
if len(in) == 0 {
return errors.New("Unable to Unmarshal empty string")
}
re := regexp.MustCompile("(?s)^@([^ ]+) (.*)( @end)?$")
match := re.FindSubmatch(in)
if len(match) == 0 {
return fmt.Errorf("Failed to match %s", in)
}
m.Key = string(match[1])
return m.processMeta(match[2])
}
func (m *Meta) processMeta(in []byte) error {
if len(in) == 0 {
return errors.New("No value found")
}
s := strings.TrimSpace(string(in))
if len(s) == 0 {
return errors.New("No value found")
}
yesno := regexp.MustCompile("^(y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)$")
yes := regexp.MustCompile("^(y|Y|yes|Yes|YES|true|True|TRUE|on|On|ON)$")
null := regexp.MustCompile("^(~|null|Null|NULL|none|None|NONE|nil|Nil|NIL)$")
var j json.RawMessage
if null.MatchString(s) {
m.Value = nil
} else if yesno.MatchString(s) {
if yes.MatchString(s) {
m.Value = true
} else {
m.Value = false
}
} else if i, err := strconv.Atoi(s); err == nil {
m.Value = i
} else if f, err := strconv.ParseFloat(s, 64); err == nil {
m.Value = f
} else if t, err := time.Parse(time.RFC3339, s); err == nil {
m.Value = t
} else if err := json.Unmarshal(in, &j); err == nil {
m.Value = j
} else {
m.Value = s
}
return nil
}