summaryrefslogtreecommitdiff
path: root/vendor/github.com/pquerna/ffjson/inception/encoder.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/pquerna/ffjson/inception/encoder.go')
-rw-r--r--vendor/github.com/pquerna/ffjson/inception/encoder.go544
1 files changed, 0 insertions, 544 deletions
diff --git a/vendor/github.com/pquerna/ffjson/inception/encoder.go b/vendor/github.com/pquerna/ffjson/inception/encoder.go
deleted file mode 100644
index 3e37a2814..000000000
--- a/vendor/github.com/pquerna/ffjson/inception/encoder.go
+++ /dev/null
@@ -1,544 +0,0 @@
-/**
- * Copyright 2014 Paul Querna
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package ffjsoninception
-
-import (
- "fmt"
- "reflect"
-
- "github.com/pquerna/ffjson/shared"
-)
-
-func typeInInception(ic *Inception, typ reflect.Type, f shared.Feature) bool {
- for _, v := range ic.objs {
- if v.Typ == typ {
- return v.Options.HasFeature(f)
- }
- if typ.Kind() == reflect.Ptr {
- if v.Typ == typ.Elem() {
- return v.Options.HasFeature(f)
- }
- }
- }
-
- return false
-}
-
-func getOmitEmpty(ic *Inception, sf *StructField) string {
- ptname := "j." + sf.Name
- if sf.Pointer {
- ptname = "*" + ptname
- return "if true {\n"
- }
- switch sf.Typ.Kind() {
-
- case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
- return "if len(" + ptname + ") != 0 {" + "\n"
-
- case reflect.Int,
- reflect.Int8,
- reflect.Int16,
- reflect.Int32,
- reflect.Int64,
- reflect.Uint,
- reflect.Uint8,
- reflect.Uint16,
- reflect.Uint32,
- reflect.Uint64,
- reflect.Uintptr,
- reflect.Float32,
- reflect.Float64:
- return "if " + ptname + " != 0 {" + "\n"
-
- case reflect.Bool:
- return "if " + ptname + " != false {" + "\n"
-
- case reflect.Interface, reflect.Ptr:
- return "if " + ptname + " != nil {" + "\n"
-
- default:
- // TODO(pquerna): fix types
- return "if true {" + "\n"
- }
-}
-
-func getMapValue(ic *Inception, name string, typ reflect.Type, ptr bool, forceString bool) string {
- var out = ""
-
- if typ.Key().Kind() != reflect.String {
- out += fmt.Sprintf("/* Falling back. type=%v kind=%v */\n", typ, typ.Kind())
- out += ic.q.Flush()
- out += "err = buf.Encode(" + name + ")" + "\n"
- out += "if err != nil {" + "\n"
- out += " return err" + "\n"
- out += "}" + "\n"
- return out
- }
-
- var elemKind reflect.Kind
- elemKind = typ.Elem().Kind()
-
- switch elemKind {
- case reflect.String,
- reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
- reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
- reflect.Float32,
- reflect.Float64,
- reflect.Bool:
-
- ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true
-
- out += "if " + name + " == nil {" + "\n"
- ic.q.Write("null")
- out += ic.q.GetQueued()
- ic.q.DeleteLast()
- out += "} else {" + "\n"
- out += ic.q.WriteFlush("{ ")
- out += " for key, value := range " + name + " {" + "\n"
- out += " fflib.WriteJsonString(buf, key)" + "\n"
- out += " buf.WriteString(`:`)" + "\n"
- out += getGetInnerValue(ic, "value", typ.Elem(), false, forceString)
- out += " buf.WriteByte(',')" + "\n"
- out += " }" + "\n"
- out += "buf.Rewind(1)" + "\n"
- out += ic.q.WriteFlush("}")
- out += "}" + "\n"
-
- default:
- out += ic.q.Flush()
- out += fmt.Sprintf("/* Falling back. type=%v kind=%v */\n", typ, typ.Kind())
- out += "err = buf.Encode(" + name + ")" + "\n"
- out += "if err != nil {" + "\n"
- out += " return err" + "\n"
- out += "}" + "\n"
- }
- return out
-}
-
-func getGetInnerValue(ic *Inception, name string, typ reflect.Type, ptr bool, forceString bool) string {
- var out = ""
-
- // Flush if not bool or maps
- if typ.Kind() != reflect.Bool && typ.Kind() != reflect.Map && typ.Kind() != reflect.Struct {
- out += ic.q.Flush()
- }
-
- if typ.Implements(marshalerFasterType) ||
- reflect.PtrTo(typ).Implements(marshalerFasterType) ||
- typeInInception(ic, typ, shared.MustEncoder) ||
- typ.Implements(marshalerType) ||
- reflect.PtrTo(typ).Implements(marshalerType) {
-
- out += ic.q.Flush()
- out += tplStr(encodeTpl["handleMarshaler"], handleMarshaler{
- IC: ic,
- Name: name,
- Typ: typ,
- Ptr: reflect.Ptr,
- MarshalJSONBuf: typ.Implements(marshalerFasterType) || reflect.PtrTo(typ).Implements(marshalerFasterType) || typeInInception(ic, typ, shared.MustEncoder),
- Marshaler: typ.Implements(marshalerType) || reflect.PtrTo(typ).Implements(marshalerType),
- })
- return out
- }
-
- ptname := name
- if ptr {
- ptname = "*" + name
- }
-
- switch typ.Kind() {
- case reflect.Int,
- reflect.Int8,
- reflect.Int16,
- reflect.Int32,
- reflect.Int64:
- ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true
- out += "fflib.FormatBits2(buf, uint64(" + ptname + "), 10, " + ptname + " < 0)" + "\n"
- case reflect.Uint,
- reflect.Uint8,
- reflect.Uint16,
- reflect.Uint32,
- reflect.Uint64,
- reflect.Uintptr:
- ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true
- out += "fflib.FormatBits2(buf, uint64(" + ptname + "), 10, false)" + "\n"
- case reflect.Float32:
- ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true
- out += "fflib.AppendFloat(buf, float64(" + ptname + "), 'g', -1, 32)" + "\n"
- case reflect.Float64:
- ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true
- out += "fflib.AppendFloat(buf, float64(" + ptname + "), 'g', -1, 64)" + "\n"
- case reflect.Array,
- reflect.Slice:
-
- // Arrays cannot be nil
- if typ.Kind() != reflect.Array {
- out += "if " + name + "!= nil {" + "\n"
- }
- // Array and slice values encode as JSON arrays, except that
- // []byte encodes as a base64-encoded string, and a nil slice
- // encodes as the null JSON object.
- if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
- ic.OutputImports[`"encoding/base64"`] = true
-
- out += "buf.WriteString(`\"`)" + "\n"
- out += `{` + "\n"
- out += `enc := base64.NewEncoder(base64.StdEncoding, buf)` + "\n"
- if typ.Elem().Name() != "byte" {
- ic.OutputImports[`"reflect"`] = true
- out += `enc.Write(reflect.Indirect(reflect.ValueOf(` + ptname + `)).Bytes())` + "\n"
-
- } else {
- out += `enc.Write(` + ptname + `)` + "\n"
- }
- out += `enc.Close()` + "\n"
- out += `}` + "\n"
- out += "buf.WriteString(`\"`)" + "\n"
- } else {
- out += "buf.WriteString(`[`)" + "\n"
- out += "for i, v := range " + ptname + "{" + "\n"
- out += "if i != 0 {" + "\n"
- out += "buf.WriteString(`,`)" + "\n"
- out += "}" + "\n"
- out += getGetInnerValue(ic, "v", typ.Elem(), false, false)
- out += "}" + "\n"
- out += "buf.WriteString(`]`)" + "\n"
- }
- if typ.Kind() != reflect.Array {
- out += "} else {" + "\n"
- out += "buf.WriteString(`null`)" + "\n"
- out += "}" + "\n"
- }
- case reflect.String:
- // Is it a json.Number?
- if typ.PkgPath() == "encoding/json" && typ.Name() == "Number" {
- // Fall back to json package to rely on the valid number check.
- // See: https://github.com/golang/go/blob/92cd6e3af9f423ab4d8ac78f24e7fd81c31a8ce6/src/encoding/json/encode.go#L550
- out += fmt.Sprintf("/* json.Number */\n")
- out += "err = buf.Encode(" + name + ")" + "\n"
- out += "if err != nil {" + "\n"
- out += " return err" + "\n"
- out += "}" + "\n"
- } else {
- ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true
- if forceString {
- // Forcestring on strings does double-escaping of the entire value.
- // We create a temporary buffer, encode to that an re-encode it.
- out += "{" + "\n"
- out += "tmpbuf := fflib.Buffer{}" + "\n"
- out += "tmpbuf.Grow(len(" + ptname + ") + 16)" + "\n"
- out += "fflib.WriteJsonString(&tmpbuf, string(" + ptname + "))" + "\n"
- out += "fflib.WriteJsonString(buf, string( tmpbuf.Bytes() " + `))` + "\n"
- out += "}" + "\n"
- } else {
- out += "fflib.WriteJsonString(buf, string(" + ptname + "))" + "\n"
- }
- }
- case reflect.Ptr:
- out += "if " + name + "!= nil {" + "\n"
- switch typ.Elem().Kind() {
- case reflect.Struct:
- out += getGetInnerValue(ic, name, typ.Elem(), false, false)
- default:
- out += getGetInnerValue(ic, "*"+name, typ.Elem(), false, false)
- }
- out += "} else {" + "\n"
- out += "buf.WriteString(`null`)" + "\n"
- out += "}" + "\n"
- case reflect.Bool:
- out += "if " + ptname + " {" + "\n"
- ic.q.Write("true")
- out += ic.q.GetQueued()
- out += "} else {" + "\n"
- // Delete 'true'
- ic.q.DeleteLast()
- out += ic.q.WriteFlush("false")
- out += "}" + "\n"
- case reflect.Interface:
- out += fmt.Sprintf("/* Interface types must use runtime reflection. type=%v kind=%v */\n", typ, typ.Kind())
- out += "err = buf.Encode(" + name + ")" + "\n"
- out += "if err != nil {" + "\n"
- out += " return err" + "\n"
- out += "}" + "\n"
- case reflect.Map:
- out += getMapValue(ic, ptname, typ, ptr, forceString)
- case reflect.Struct:
- if typ.Name() == "" {
- ic.q.Write("{")
- ic.q.Write(" ")
- out += fmt.Sprintf("/* Inline struct. type=%v kind=%v */\n", typ, typ.Kind())
- newV := reflect.Indirect(reflect.New(typ)).Interface()
- fields := extractFields(newV)
-
- // Output all fields
- for _, field := range fields {
- // Adjust field name
- field.Name = name + "." + field.Name
- out += getField(ic, field, "")
- }
-
- if lastConditional(fields) {
- out += ic.q.Flush()
- out += `buf.Rewind(1)` + "\n"
- } else {
- ic.q.DeleteLast()
- }
- out += ic.q.WriteFlush("}")
- } else {
- out += fmt.Sprintf("/* Struct fall back. type=%v kind=%v */\n", typ, typ.Kind())
- out += ic.q.Flush()
- if ptr {
- out += "err = buf.Encode(" + name + ")" + "\n"
- } else {
- // We send pointer to avoid copying entire struct
- out += "err = buf.Encode(&" + name + ")" + "\n"
- }
- out += "if err != nil {" + "\n"
- out += " return err" + "\n"
- out += "}" + "\n"
- }
- default:
- out += fmt.Sprintf("/* Falling back. type=%v kind=%v */\n", typ, typ.Kind())
- out += "err = buf.Encode(" + name + ")" + "\n"
- out += "if err != nil {" + "\n"
- out += " return err" + "\n"
- out += "}" + "\n"
- }
-
- return out
-}
-
-func getValue(ic *Inception, sf *StructField, prefix string) string {
- closequote := false
- if sf.ForceString {
- switch sf.Typ.Kind() {
- case reflect.Int,
- reflect.Int8,
- reflect.Int16,
- reflect.Int32,
- reflect.Int64,
- reflect.Uint,
- reflect.Uint8,
- reflect.Uint16,
- reflect.Uint32,
- reflect.Uint64,
- reflect.Uintptr,
- reflect.Float32,
- reflect.Float64,
- reflect.Bool:
- ic.q.Write(`"`)
- closequote = true
- }
- }
- out := getGetInnerValue(ic, prefix+sf.Name, sf.Typ, sf.Pointer, sf.ForceString)
- if closequote {
- if sf.Pointer {
- out += ic.q.WriteFlush(`"`)
- } else {
- ic.q.Write(`"`)
- }
- }
-
- return out
-}
-
-func p2(v uint32) uint32 {
- v--
- v |= v >> 1
- v |= v >> 2
- v |= v >> 4
- v |= v >> 8
- v |= v >> 16
- v++
- return v
-}
-
-func getTypeSize(t reflect.Type) uint32 {
- switch t.Kind() {
- case reflect.String:
- // TODO: consider runtime analysis.
- return 32
- case reflect.Array, reflect.Map, reflect.Slice:
- // TODO: consider runtime analysis.
- return 4 * getTypeSize(t.Elem())
- case reflect.Int,
- reflect.Int8,
- reflect.Int16,
- reflect.Int32,
- reflect.Uint,
- reflect.Uint8,
- reflect.Uint16,
- reflect.Uint32:
- return 8
- case reflect.Int64,
- reflect.Uint64,
- reflect.Uintptr:
- return 16
- case reflect.Float32,
- reflect.Float64:
- return 16
- case reflect.Bool:
- return 4
- case reflect.Ptr:
- return getTypeSize(t.Elem())
- default:
- return 16
- }
-}
-
-func getTotalSize(si *StructInfo) uint32 {
- rv := uint32(si.Typ.Size())
- for _, f := range si.Fields {
- rv += getTypeSize(f.Typ)
- }
- return rv
-}
-
-func getBufGrowSize(si *StructInfo) uint32 {
-
- // TOOD(pquerna): automatically calc a better grow size based on history
- // of a struct.
- return p2(getTotalSize(si))
-}
-
-func isIntish(t reflect.Type) bool {
- if t.Kind() >= reflect.Int && t.Kind() <= reflect.Uintptr {
- return true
- }
- if t.Kind() == reflect.Array || t.Kind() == reflect.Slice || t.Kind() == reflect.Ptr {
- if t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 {
- // base64 special case.
- return false
- } else {
- return isIntish(t.Elem())
- }
- }
- return false
-}
-
-func getField(ic *Inception, f *StructField, prefix string) string {
- out := ""
- if f.OmitEmpty {
- out += ic.q.Flush()
- if f.Pointer {
- out += "if " + prefix + f.Name + " != nil {" + "\n"
- }
- out += getOmitEmpty(ic, f)
- }
-
- if f.Pointer && !f.OmitEmpty {
- // Pointer values encode as the value pointed to. A nil pointer encodes as the null JSON object.
- out += "if " + prefix + f.Name + " != nil {" + "\n"
- }
-
- // JsonName is already escaped and quoted.
- // getInnervalue should flush
- ic.q.Write(f.JsonName + ":")
- // We save a copy in case we need it
- t := ic.q
-
- out += getValue(ic, f, prefix)
- ic.q.Write(",")
-
- if f.Pointer && !f.OmitEmpty {
- out += "} else {" + "\n"
- out += t.WriteFlush("null")
- out += "}" + "\n"
- }
-
- if f.OmitEmpty {
- out += ic.q.Flush()
- if f.Pointer {
- out += "}" + "\n"
- }
- out += "}" + "\n"
- }
- return out
-}
-
-// We check if the last field is conditional.
-func lastConditional(fields []*StructField) bool {
- if len(fields) > 0 {
- f := fields[len(fields)-1]
- return f.OmitEmpty
- }
- return false
-}
-
-func CreateMarshalJSON(ic *Inception, si *StructInfo) error {
- conditionalWrites := lastConditional(si.Fields)
- out := ""
-
- out += "// MarshalJSON marshal bytes to json - template\n"
- out += `func (j *` + si.Name + `) MarshalJSON() ([]byte, error) {` + "\n"
- out += `var buf fflib.Buffer` + "\n"
-
- out += `if j == nil {` + "\n"
- out += ` buf.WriteString("null")` + "\n"
- out += " return buf.Bytes(), nil" + "\n"
- out += `}` + "\n"
-
- out += `err := j.MarshalJSONBuf(&buf)` + "\n"
- out += `if err != nil {` + "\n"
- out += " return nil, err" + "\n"
- out += `}` + "\n"
- out += `return buf.Bytes(), nil` + "\n"
- out += `}` + "\n"
-
- out += "// MarshalJSONBuf marshal buff to json - template\n"
- out += `func (j *` + si.Name + `) MarshalJSONBuf(buf fflib.EncodingBuffer) (error) {` + "\n"
- out += ` if j == nil {` + "\n"
- out += ` buf.WriteString("null")` + "\n"
- out += " return nil" + "\n"
- out += ` }` + "\n"
-
- out += `var err error` + "\n"
- out += `var obj []byte` + "\n"
- out += `_ = obj` + "\n"
- out += `_ = err` + "\n"
-
- ic.q.Write("{")
-
- // The extra space is inserted here.
- // If nothing is written to the field this will be deleted
- // instead of the last comma.
- if conditionalWrites || len(si.Fields) == 0 {
- ic.q.Write(" ")
- }
-
- for _, f := range si.Fields {
- out += getField(ic, f, "j.")
- }
-
- // Handling the last comma is tricky.
- // If the last field has omitempty, conditionalWrites is set.
- // If something has been written, we delete the last comma,
- // by backing up the buffer, otherwise it will delete a space.
- if conditionalWrites {
- out += ic.q.Flush()
- out += `buf.Rewind(1)` + "\n"
- } else {
- ic.q.DeleteLast()
- }
-
- out += ic.q.WriteFlush("}")
- out += `return nil` + "\n"
- out += `}` + "\n"
- ic.OutputFuncs = append(ic.OutputFuncs, out)
- return nil
-}