Files
transit/content/content.go
2025-05-21 22:42:51 -01:06

62 lines
1.6 KiB
Go

package content
import (
"bytes"
"encoding/base64"
"github.com/mleku/transit/chk"
"github.com/mleku/transit/errorf"
"github.com/mleku/transit/text"
)
var BinaryPrefix = []byte("base64:")
// C is a content field for an event.T that can be binary or text, if set to binary, it encodes
// to base64 URL format (with padding). Binary coded values have the prefix "base64:" prefix.
// Setting binary should be done in accordance with the mimetype being a binary mimetype.
type C struct {
Val []byte
Binary bool
}
// New creates a new mime.Type based on input string or bytes of value.
func New[V []byte | string](c V, binary bool) (content *C) {
content = &C{Val: []byte(c), Binary: binary}
return
}
func (c *C) MarshalJSON() (b []byte, err error) {
if c.Binary {
b = make([]byte, base64.URLEncoding.EncodedLen(len(c.Val))+2+len(BinaryPrefix))
copy(b[1:], BinaryPrefix)
base64.URLEncoding.Encode(b[1+len(BinaryPrefix):len(b)-1], c.Val)
b[0] = '"'
b[len(b)-1] = '"'
} else {
b = append(append([]byte{'"'}, text.Escape(nil, c.Val)...), '"')
}
return
}
func (c *C) UnmarshalJSON(b []byte) (err error) {
b = b[1:]
if bytes.HasPrefix(b, BinaryPrefix) {
c.Binary = true
// remove quotes and binary prefix
b = b[len(BinaryPrefix) : len(b)-1]
var n int
// we use AppendDecode to avoid needing to trim pad bytes
if c.Val, err = base64.URLEncoding.AppendDecode(c.Val, b); chk.E(err) {
err = errorf.E("error: decoding failed at %d: %s", n, err.Error())
return
}
c.Binary = true
} else {
b = b[:len(b)-1]
c.Val = b
c.Val = text.Unescape(c.Val)
c.Binary = false
}
return
}