mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
302 lines
7.6 KiB
Go
302 lines
7.6 KiB
Go
package entity
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"unsafe"
|
|
|
|
jsoniter "github.com/json-iterator/go"
|
|
)
|
|
|
|
func init() { //nolint:gochecknoinits
|
|
jsoniter.RegisterTypeEncoder("entity.EntitySearchResult", &searchResultCodec{})
|
|
jsoniter.RegisterTypeEncoder("entity.WriteEntityResponse", &writeResponseCodec{})
|
|
|
|
jsoniter.RegisterTypeEncoder("entity.Entity", &rawEntityCodec{})
|
|
jsoniter.RegisterTypeDecoder("entity.Entity", &rawEntityCodec{})
|
|
}
|
|
|
|
func writeRawJson(stream *jsoniter.Stream, val []byte) {
|
|
if json.Valid(val) {
|
|
_, _ = stream.Write(val)
|
|
} else {
|
|
stream.WriteString(string(val))
|
|
}
|
|
}
|
|
|
|
// Unlike the standard JSON marshal, this will write bytes as JSON when it can
|
|
type rawEntityCodec struct{}
|
|
|
|
func (obj *Entity) MarshalJSON() ([]byte, error) {
|
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
|
return json.Marshal(obj)
|
|
}
|
|
|
|
// UnmarshalJSON will read JSON into a Entity
|
|
func (obj *Entity) UnmarshalJSON(b []byte) error {
|
|
if obj == nil {
|
|
return fmt.Errorf("unexpected nil for raw objcet")
|
|
}
|
|
iter := jsoniter.ParseBytes(jsoniter.ConfigDefault, b)
|
|
readEntity(iter, obj)
|
|
return iter.Error
|
|
}
|
|
|
|
func (codec *rawEntityCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
|
f := (*Entity)(ptr)
|
|
return f.GRN == nil && f.Body == nil
|
|
}
|
|
|
|
func (codec *rawEntityCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
|
obj := (*Entity)(ptr)
|
|
stream.WriteObjectStart()
|
|
stream.WriteObjectField("GRN")
|
|
stream.WriteVal(obj.GRN)
|
|
|
|
if obj.Version != "" {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("version")
|
|
stream.WriteString(obj.Version)
|
|
}
|
|
if obj.CreatedAt > 0 {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("createdAt")
|
|
stream.WriteInt64(obj.CreatedAt)
|
|
}
|
|
if obj.UpdatedAt > 0 {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("updatedAt")
|
|
stream.WriteInt64(obj.UpdatedAt)
|
|
}
|
|
if obj.CreatedBy != "" {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("createdBy")
|
|
stream.WriteString(obj.CreatedBy)
|
|
}
|
|
if obj.UpdatedBy != "" {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("updatedBy")
|
|
stream.WriteString(obj.UpdatedBy)
|
|
}
|
|
if obj.Folder != "" {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("folder")
|
|
stream.WriteString(obj.Folder)
|
|
}
|
|
if obj.Body != nil {
|
|
stream.WriteMore()
|
|
if json.Valid(obj.Body) {
|
|
stream.WriteObjectField("body")
|
|
stream.WriteRaw(string(obj.Body)) // works for strings
|
|
} else {
|
|
sEnc := base64.StdEncoding.EncodeToString(obj.Body)
|
|
stream.WriteObjectField("body_base64")
|
|
stream.WriteString(sEnc) // works for strings
|
|
}
|
|
}
|
|
if len(obj.SummaryJson) > 0 {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("summary")
|
|
writeRawJson(stream, obj.SummaryJson)
|
|
}
|
|
if obj.ETag != "" {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("etag")
|
|
stream.WriteString(obj.ETag)
|
|
}
|
|
if obj.Size > 0 {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("size")
|
|
stream.WriteInt64(obj.Size)
|
|
}
|
|
if obj.Origin != nil {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("origin")
|
|
stream.WriteVal(obj.Origin)
|
|
}
|
|
stream.WriteObjectEnd()
|
|
}
|
|
|
|
func (codec *rawEntityCodec) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
|
*(*Entity)(ptr) = Entity{}
|
|
raw := (*Entity)(ptr)
|
|
readEntity(iter, raw)
|
|
}
|
|
|
|
func readEntity(iter *jsoniter.Iterator, raw *Entity) {
|
|
for l1Field := iter.ReadObject(); l1Field != ""; l1Field = iter.ReadObject() {
|
|
switch l1Field {
|
|
case "GRN":
|
|
raw.GRN = &GRN{}
|
|
iter.ReadVal(raw.GRN)
|
|
case "updatedAt":
|
|
raw.UpdatedAt = iter.ReadInt64()
|
|
case "updatedBy":
|
|
raw.UpdatedBy = iter.ReadString()
|
|
case "createdAt":
|
|
raw.CreatedAt = iter.ReadInt64()
|
|
case "createdBy":
|
|
raw.CreatedBy = iter.ReadString()
|
|
case "size":
|
|
raw.Size = iter.ReadInt64()
|
|
case "etag":
|
|
raw.ETag = iter.ReadString()
|
|
case "version":
|
|
raw.Version = iter.ReadString()
|
|
case "folder":
|
|
raw.Folder = iter.ReadString()
|
|
case "origin":
|
|
raw.Origin = &EntityOriginInfo{}
|
|
iter.ReadVal(raw.Origin)
|
|
case "summary":
|
|
var val interface{}
|
|
iter.ReadVal(&val) // ??? is there a smarter way to just keep the underlying bytes without read+marshal
|
|
body, err := json.Marshal(val)
|
|
if err != nil {
|
|
iter.ReportError("raw entity", "error reading summary body")
|
|
return
|
|
}
|
|
raw.SummaryJson = body
|
|
|
|
case "body":
|
|
var val interface{}
|
|
iter.ReadVal(&val) // ??? is there a smarter way to just keep the underlying bytes without read+marshal
|
|
body, err := json.Marshal(val)
|
|
if err != nil {
|
|
iter.ReportError("raw entity", "error creating json from body")
|
|
return
|
|
}
|
|
raw.Body = body
|
|
|
|
case "body_base64":
|
|
val := iter.ReadString()
|
|
body, err := base64.StdEncoding.DecodeString(val)
|
|
if err != nil {
|
|
iter.ReportError("raw entity", "error decoding base64 body")
|
|
return
|
|
}
|
|
raw.Body = body
|
|
|
|
default:
|
|
iter.ReportError("raw object", "unexpected field: "+l1Field)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// Unlike the standard JSON marshal, this will write bytes as JSON when it can
|
|
type searchResultCodec struct{}
|
|
|
|
func (obj *EntitySearchResult) MarshalJSON() ([]byte, error) {
|
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
|
return json.Marshal(obj)
|
|
}
|
|
|
|
func (codec *searchResultCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
|
f := (*EntitySearchResult)(ptr)
|
|
return f.GRN == nil && f.Body == nil
|
|
}
|
|
|
|
func (codec *searchResultCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
|
obj := (*EntitySearchResult)(ptr)
|
|
stream.WriteObjectStart()
|
|
stream.WriteObjectField("GRN")
|
|
stream.WriteVal(obj.GRN)
|
|
|
|
if obj.Name != "" {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("name")
|
|
stream.WriteString(obj.Name)
|
|
}
|
|
if obj.Description != "" {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("description")
|
|
stream.WriteString(obj.Description)
|
|
}
|
|
if obj.Size > 0 {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("size")
|
|
stream.WriteInt64(obj.Size)
|
|
}
|
|
if obj.UpdatedAt > 0 {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("updatedAt")
|
|
stream.WriteInt64(obj.UpdatedAt)
|
|
}
|
|
if obj.UpdatedBy != "" {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("updatedBy")
|
|
stream.WriteVal(obj.UpdatedBy)
|
|
}
|
|
if obj.Body != nil {
|
|
stream.WriteMore()
|
|
if json.Valid(obj.Body) {
|
|
stream.WriteObjectField("body")
|
|
_, _ = stream.Write(obj.Body) // works for strings
|
|
} else {
|
|
stream.WriteObjectField("body_base64")
|
|
stream.WriteVal(obj.Body) // works for strings
|
|
}
|
|
}
|
|
if obj.Labels != nil {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("labels")
|
|
stream.WriteVal(obj.Labels)
|
|
}
|
|
if obj.ErrorJson != nil {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("error")
|
|
writeRawJson(stream, obj.ErrorJson)
|
|
}
|
|
if obj.FieldsJson != nil {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("fields")
|
|
writeRawJson(stream, obj.FieldsJson)
|
|
}
|
|
|
|
stream.WriteObjectEnd()
|
|
}
|
|
|
|
// Unlike the standard JSON marshal, this will write bytes as JSON when it can
|
|
type writeResponseCodec struct{}
|
|
|
|
func (obj *WriteEntityResponse) MarshalJSON() ([]byte, error) {
|
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
|
return json.Marshal(obj)
|
|
}
|
|
|
|
func (codec *writeResponseCodec) IsEmpty(ptr unsafe.Pointer) bool {
|
|
f := (*WriteEntityResponse)(ptr)
|
|
return f == nil
|
|
}
|
|
|
|
func (codec *writeResponseCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
|
obj := (*WriteEntityResponse)(ptr)
|
|
stream.WriteObjectStart()
|
|
stream.WriteObjectField("status")
|
|
stream.WriteString(obj.Status.String())
|
|
|
|
if obj.Error != nil {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("error")
|
|
stream.WriteVal(obj.Error)
|
|
}
|
|
if obj.GRN != nil {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("GRN")
|
|
stream.WriteVal(obj.GRN)
|
|
}
|
|
if obj.Entity != nil {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("entity")
|
|
stream.WriteVal(obj.Entity)
|
|
}
|
|
if len(obj.SummaryJson) > 0 {
|
|
stream.WriteMore()
|
|
stream.WriteObjectField("summary")
|
|
writeRawJson(stream, obj.SummaryJson)
|
|
}
|
|
stream.WriteObjectEnd()
|
|
}
|