package models import ( "bytes" "encoding/json" "errors" "fmt" "regexp" "codeberg.org/danjones000/my-log/tools" ) 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 not allowed in key: %s", m.Key) } 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 { buff.WriteRune('@') buff.WriteString(m.Key) buff.WriteRune(' ') n, err := tools.WriteValue(buff, m.Value) if err != nil { return err } if n == 0 { return ErrorParsing } return nil } func (m *Meta) UnmarshalText(in []byte) error { if len(in) == 0 { return newParsingError(errors.New("Unable to Unmarshal empty string")) } re := regexp.MustCompile("(?s)^@([^ ]+) (.*)( @end)?$") match := re.FindSubmatch(in) if len(match) == 0 { return newParsingError(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 newParsingError(errors.New("No value found")) } v := tools.ParseBytes(in) if v == "" { return newParsingError(errors.New("No value found")) } m.Value = v return nil }