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 }