my-log/models/meta.go

109 lines
2.1 KiB
Go
Raw Permalink Normal View History

2024-01-26 19:40:38 -06:00
package models
2024-01-26 20:00:03 -06:00
import (
"bytes"
"encoding/json"
2024-01-27 16:07:27 -06:00
"errors"
2024-01-26 20:00:03 -06:00
"fmt"
"regexp"
2024-02-09 09:44:35 -06:00
"codeberg.org/danjones000/my-log/tools"
2024-01-26 20:00:03 -06:00
)
type Meta struct {
Key string
Value any
}
func (m Meta) MarshalText() ([]byte, error) {
if regexp.MustCompile(`\s`).MatchString(m.Key) {
2024-01-27 16:07:27 -06:00
return []byte{}, fmt.Errorf("whitespace is not allowed in key: %s", m.Key)
2024-01-26 20:00:03 -06:00
}
2024-01-26 20:00:03 -06:00
buff := &bytes.Buffer{}
if jv, ok := m.Value.(map[string]any); ok {
err := marshalMap(m.Key, jv, buff)
return buff.Bytes(), err
}
if jj, ok := m.Value.(json.RawMessage); ok {
mp := map[string]any{}
err := json.Unmarshal(jj, &mp)
if err == nil {
err := marshalMap(m.Key, mp, buff)
return buff.Bytes(), err
}
}
if err := m.marshalToBuff(buff); err != nil {
return nil, err
}
return buff.Bytes(), nil
}
func marshalMap(pre string, mp map[string]any, buff *bytes.Buffer) error {
var idx uint
for k, v := range mp {
if idx > 0 {
buff.WriteRune('\n')
}
idx++
newKey := pre + ":" + k
if k == "." || k == "" {
newKey = pre
}
if subM, ok := v.(map[string]any); ok {
if err := marshalMap(newKey, subM, buff); err != nil {
return err
}
} else {
mSub := Meta{newKey, v}
if err := mSub.marshalToBuff(buff); err != nil {
return err
}
}
}
return nil
}
func (m Meta) marshalToBuff(buff *bytes.Buffer) error {
2024-01-26 20:00:03 -06:00
buff.WriteRune('@')
buff.WriteString(m.Key)
buff.WriteRune(' ')
2024-03-03 13:56:48 -06:00
n, err := tools.WriteValue(buff, m.Value)
if err != nil {
return err
2024-01-26 20:00:03 -06:00
}
if n == 0 {
return ErrorParsing
}
return nil
2024-01-26 20:00:03 -06:00
}
2024-01-27 16:07:27 -06:00
func (m *Meta) UnmarshalText(in []byte) error {
if len(in) == 0 {
2024-01-28 12:41:55 -06:00
return newParsingError(errors.New("Unable to Unmarshal empty string"))
2024-01-27 16:07:27 -06:00
}
re := regexp.MustCompile("(?s)^@([^ ]+) (.*)( @end)?$")
match := re.FindSubmatch(in)
if len(match) == 0 {
2024-01-28 12:41:55 -06:00
return newParsingError(fmt.Errorf("Failed to match %s", in))
2024-01-27 16:07:27 -06:00
}
m.Key = string(match[1])
return m.processMeta(match[2])
}
func (m *Meta) processMeta(in []byte) error {
if len(in) == 0 {
2024-01-28 12:41:55 -06:00
return newParsingError(errors.New("No value found"))
2024-01-27 16:07:27 -06:00
}
2024-02-09 09:44:35 -06:00
v := tools.ParseBytes(in)
if v == "" {
2024-01-28 12:41:55 -06:00
return newParsingError(errors.New("No value found"))
2024-01-27 16:07:27 -06:00
}
2024-02-09 09:44:35 -06:00
m.Value = v
2024-01-27 16:07:27 -06:00
return nil
}