From 961c04cae992eadb42d286d2f85f8a675bdc68c8 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Mon, 29 Jan 2018 14:17:40 -0800 Subject: Upgrading server dependancies (#8154) --- vendor/github.com/mailru/easyjson/gen/encoder.go | 382 +++++++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 vendor/github.com/mailru/easyjson/gen/encoder.go (limited to 'vendor/github.com/mailru/easyjson/gen/encoder.go') diff --git a/vendor/github.com/mailru/easyjson/gen/encoder.go b/vendor/github.com/mailru/easyjson/gen/encoder.go new file mode 100644 index 000000000..48cba15d4 --- /dev/null +++ b/vendor/github.com/mailru/easyjson/gen/encoder.go @@ -0,0 +1,382 @@ +package gen + +import ( + "encoding" + "encoding/json" + "fmt" + "reflect" + "strconv" + "strings" + + "github.com/mailru/easyjson" +) + +func (g *Generator) getEncoderName(t reflect.Type) string { + return g.functionName("encode", t) +} + +var primitiveEncoders = map[reflect.Kind]string{ + reflect.String: "out.String(string(%v))", + reflect.Bool: "out.Bool(bool(%v))", + reflect.Int: "out.Int(int(%v))", + reflect.Int8: "out.Int8(int8(%v))", + reflect.Int16: "out.Int16(int16(%v))", + reflect.Int32: "out.Int32(int32(%v))", + reflect.Int64: "out.Int64(int64(%v))", + reflect.Uint: "out.Uint(uint(%v))", + reflect.Uint8: "out.Uint8(uint8(%v))", + reflect.Uint16: "out.Uint16(uint16(%v))", + reflect.Uint32: "out.Uint32(uint32(%v))", + reflect.Uint64: "out.Uint64(uint64(%v))", + reflect.Float32: "out.Float32(float32(%v))", + reflect.Float64: "out.Float64(float64(%v))", +} + +var primitiveStringEncoders = map[reflect.Kind]string{ + reflect.String: "out.String(string(%v))", + reflect.Int: "out.IntStr(int(%v))", + reflect.Int8: "out.Int8Str(int8(%v))", + reflect.Int16: "out.Int16Str(int16(%v))", + reflect.Int32: "out.Int32Str(int32(%v))", + reflect.Int64: "out.Int64Str(int64(%v))", + reflect.Uint: "out.UintStr(uint(%v))", + reflect.Uint8: "out.Uint8Str(uint8(%v))", + reflect.Uint16: "out.Uint16Str(uint16(%v))", + reflect.Uint32: "out.Uint32Str(uint32(%v))", + reflect.Uint64: "out.Uint64Str(uint64(%v))", + reflect.Uintptr: "out.UintptrStr(uintptr(%v))", +} + +// fieldTags contains parsed version of json struct field tags. +type fieldTags struct { + name string + + omit bool + omitEmpty bool + noOmitEmpty bool + asString bool + required bool +} + +// parseFieldTags parses the json field tag into a structure. +func parseFieldTags(f reflect.StructField) fieldTags { + var ret fieldTags + + for i, s := range strings.Split(f.Tag.Get("json"), ",") { + switch { + case i == 0 && s == "-": + ret.omit = true + case i == 0: + ret.name = s + case s == "omitempty": + ret.omitEmpty = true + case s == "!omitempty": + ret.noOmitEmpty = true + case s == "string": + ret.asString = true + case s == "required": + ret.required = true + } + } + + return ret +} + +// genTypeEncoder generates code that encodes in of type t into the writer, but uses marshaler interface if implemented by t. +func (g *Generator) genTypeEncoder(t reflect.Type, in string, tags fieldTags, indent int, assumeNonEmpty bool) error { + ws := strings.Repeat(" ", indent) + + marshalerIface := reflect.TypeOf((*easyjson.Marshaler)(nil)).Elem() + if reflect.PtrTo(t).Implements(marshalerIface) { + fmt.Fprintln(g.out, ws+"("+in+").MarshalEasyJSON(out)") + return nil + } + + marshalerIface = reflect.TypeOf((*json.Marshaler)(nil)).Elem() + if reflect.PtrTo(t).Implements(marshalerIface) { + fmt.Fprintln(g.out, ws+"out.Raw( ("+in+").MarshalJSON() )") + return nil + } + + marshalerIface = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() + if reflect.PtrTo(t).Implements(marshalerIface) { + fmt.Fprintln(g.out, ws+"out.RawText( ("+in+").MarshalText() )") + return nil + } + + err := g.genTypeEncoderNoCheck(t, in, tags, indent, assumeNonEmpty) + return err +} + +// genTypeEncoderNoCheck generates code that encodes in of type t into the writer. +func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldTags, indent int, assumeNonEmpty bool) error { + ws := strings.Repeat(" ", indent) + + // Check whether type is primitive, needs to be done after interface check. + if enc := primitiveStringEncoders[t.Kind()]; enc != "" && tags.asString { + fmt.Fprintf(g.out, ws+enc+"\n", in) + return nil + } else if enc := primitiveEncoders[t.Kind()]; enc != "" { + fmt.Fprintf(g.out, ws+enc+"\n", in) + return nil + } + + switch t.Kind() { + case reflect.Slice: + elem := t.Elem() + iVar := g.uniqueVarName() + vVar := g.uniqueVarName() + + if t.Elem().Kind() == reflect.Uint8 { + fmt.Fprintln(g.out, ws+"out.Base64Bytes("+in+")") + } else { + if !assumeNonEmpty { + fmt.Fprintln(g.out, ws+"if "+in+" == nil && (out.Flags & jwriter.NilSliceAsEmpty) == 0 {") + fmt.Fprintln(g.out, ws+` out.RawString("null")`) + fmt.Fprintln(g.out, ws+"} else {") + } else { + fmt.Fprintln(g.out, ws+"{") + } + fmt.Fprintln(g.out, ws+" out.RawByte('[')") + fmt.Fprintln(g.out, ws+" for "+iVar+", "+vVar+" := range "+in+" {") + fmt.Fprintln(g.out, ws+" if "+iVar+" > 0 {") + fmt.Fprintln(g.out, ws+" out.RawByte(',')") + fmt.Fprintln(g.out, ws+" }") + + if err := g.genTypeEncoder(elem, vVar, tags, indent+2, false); err != nil { + return err + } + + fmt.Fprintln(g.out, ws+" }") + fmt.Fprintln(g.out, ws+" out.RawByte(']')") + fmt.Fprintln(g.out, ws+"}") + } + + case reflect.Array: + elem := t.Elem() + iVar := g.uniqueVarName() + + if t.Elem().Kind() == reflect.Uint8 { + fmt.Fprintln(g.out, ws+"out.Base64Bytes("+in+"[:])") + } else { + fmt.Fprintln(g.out, ws+"out.RawByte('[')") + fmt.Fprintln(g.out, ws+"for "+iVar+" := range "+in+" {") + fmt.Fprintln(g.out, ws+" if "+iVar+" > 0 {") + fmt.Fprintln(g.out, ws+" out.RawByte(',')") + fmt.Fprintln(g.out, ws+" }") + + if err := g.genTypeEncoder(elem, in+"["+iVar+"]", tags, indent+1, false); err != nil { + return err + } + + fmt.Fprintln(g.out, ws+"}") + fmt.Fprintln(g.out, ws+"out.RawByte(']')") + } + + case reflect.Struct: + enc := g.getEncoderName(t) + g.addType(t) + + fmt.Fprintln(g.out, ws+enc+"(out, "+in+")") + + case reflect.Ptr: + if !assumeNonEmpty { + fmt.Fprintln(g.out, ws+"if "+in+" == nil {") + fmt.Fprintln(g.out, ws+` out.RawString("null")`) + fmt.Fprintln(g.out, ws+"} else {") + } + + if err := g.genTypeEncoder(t.Elem(), "*"+in, tags, indent+1, false); err != nil { + return err + } + + if !assumeNonEmpty { + fmt.Fprintln(g.out, ws+"}") + } + + case reflect.Map: + key := t.Key() + keyEnc, ok := primitiveStringEncoders[key.Kind()] + if !ok { + return fmt.Errorf("map key type %v not supported: only string and integer keys are allowed", key) + } + tmpVar := g.uniqueVarName() + + if !assumeNonEmpty { + fmt.Fprintln(g.out, ws+"if "+in+" == nil && (out.Flags & jwriter.NilMapAsEmpty) == 0 {") + fmt.Fprintln(g.out, ws+" out.RawString(`null`)") + fmt.Fprintln(g.out, ws+"} else {") + } else { + fmt.Fprintln(g.out, ws+"{") + } + fmt.Fprintln(g.out, ws+" out.RawByte('{')") + fmt.Fprintln(g.out, ws+" "+tmpVar+"First := true") + fmt.Fprintln(g.out, ws+" for "+tmpVar+"Name, "+tmpVar+"Value := range "+in+" {") + fmt.Fprintln(g.out, ws+" if "+tmpVar+"First { "+tmpVar+"First = false } else { out.RawByte(',') }") + fmt.Fprintln(g.out, ws+" "+fmt.Sprintf(keyEnc, tmpVar+"Name")) + fmt.Fprintln(g.out, ws+" out.RawByte(':')") + + if err := g.genTypeEncoder(t.Elem(), tmpVar+"Value", tags, indent+2, false); err != nil { + return err + } + + fmt.Fprintln(g.out, ws+" }") + fmt.Fprintln(g.out, ws+" out.RawByte('}')") + fmt.Fprintln(g.out, ws+"}") + + case reflect.Interface: + if t.NumMethod() != 0 { + return fmt.Errorf("interface type %v not supported: only interface{} is allowed", t) + } + fmt.Fprintln(g.out, ws+"if m, ok := "+in+".(easyjson.Marshaler); ok {") + fmt.Fprintln(g.out, ws+" m.MarshalEasyJSON(out)") + fmt.Fprintln(g.out, ws+"} else if m, ok := "+in+".(json.Marshaler); ok {") + fmt.Fprintln(g.out, ws+" out.Raw(m.MarshalJSON())") + fmt.Fprintln(g.out, ws+"} else {") + fmt.Fprintln(g.out, ws+" out.Raw(json.Marshal("+in+"))") + fmt.Fprintln(g.out, ws+"}") + + default: + return fmt.Errorf("don't know how to encode %v", t) + } + return nil +} + +func (g *Generator) notEmptyCheck(t reflect.Type, v string) string { + optionalIface := reflect.TypeOf((*easyjson.Optional)(nil)).Elem() + if reflect.PtrTo(t).Implements(optionalIface) { + return "(" + v + ").IsDefined()" + } + + switch t.Kind() { + case reflect.Slice, reflect.Map: + return "len(" + v + ") != 0" + case reflect.Interface, reflect.Ptr: + return v + " != nil" + case reflect.Bool: + return v + case reflect.String: + return v + ` != ""` + case reflect.Float32, reflect.Float64, + reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + + return v + " != 0" + + default: + // note: Array types don't have a useful empty value + return "true" + } +} + +func (g *Generator) genStructFieldEncoder(t reflect.Type, f reflect.StructField) error { + jsonName := g.fieldNamer.GetJSONFieldName(t, f) + tags := parseFieldTags(f) + + if tags.omit { + return nil + } + noOmitEmpty := (!tags.omitEmpty && !g.omitEmpty) || tags.noOmitEmpty + if noOmitEmpty { + fmt.Fprintln(g.out, " {") + } else { + fmt.Fprintln(g.out, " if", g.notEmptyCheck(f.Type, "in."+f.Name), "{") + } + fmt.Fprintf(g.out, " const prefix string = %q\n", ","+strconv.Quote(jsonName)+":") + fmt.Fprintln(g.out, " if first {") + fmt.Fprintln(g.out, " first = false") + fmt.Fprintln(g.out, " out.RawString(prefix[1:])") + fmt.Fprintln(g.out, " } else {") + fmt.Fprintln(g.out, " out.RawString(prefix)") + fmt.Fprintln(g.out, " }") + + if err := g.genTypeEncoder(f.Type, "in."+f.Name, tags, 2, !noOmitEmpty); err != nil { + return err + } + fmt.Fprintln(g.out, " }") + return nil +} + +func (g *Generator) genEncoder(t reflect.Type) error { + switch t.Kind() { + case reflect.Slice, reflect.Array, reflect.Map: + return g.genSliceArrayMapEncoder(t) + default: + return g.genStructEncoder(t) + } +} + +func (g *Generator) genSliceArrayMapEncoder(t reflect.Type) error { + switch t.Kind() { + case reflect.Slice, reflect.Array, reflect.Map: + default: + return fmt.Errorf("cannot generate encoder/decoder for %v, not a slice/array/map type", t) + } + + fname := g.getEncoderName(t) + typ := g.getType(t) + + fmt.Fprintln(g.out, "func "+fname+"(out *jwriter.Writer, in "+typ+") {") + err := g.genTypeEncoderNoCheck(t, "in", fieldTags{}, 1, false) + if err != nil { + return err + } + fmt.Fprintln(g.out, "}") + return nil +} + +func (g *Generator) genStructEncoder(t reflect.Type) error { + if t.Kind() != reflect.Struct { + return fmt.Errorf("cannot generate encoder/decoder for %v, not a struct type", t) + } + + fname := g.getEncoderName(t) + typ := g.getType(t) + + fmt.Fprintln(g.out, "func "+fname+"(out *jwriter.Writer, in "+typ+") {") + fmt.Fprintln(g.out, " out.RawByte('{')") + fmt.Fprintln(g.out, " first := true") + fmt.Fprintln(g.out, " _ = first") + + fs, err := getStructFields(t) + if err != nil { + return fmt.Errorf("cannot generate encoder for %v: %v", t, err) + } + for _, f := range fs { + if err := g.genStructFieldEncoder(t, f); err != nil { + return err + } + } + + fmt.Fprintln(g.out, " out.RawByte('}')") + fmt.Fprintln(g.out, "}") + + return nil +} + +func (g *Generator) genStructMarshaler(t reflect.Type) error { + switch t.Kind() { + case reflect.Slice, reflect.Array, reflect.Map, reflect.Struct: + default: + return fmt.Errorf("cannot generate encoder/decoder for %v, not a struct/slice/array/map type", t) + } + + fname := g.getEncoderName(t) + typ := g.getType(t) + + if !g.noStdMarshalers { + fmt.Fprintln(g.out, "// MarshalJSON supports json.Marshaler interface") + fmt.Fprintln(g.out, "func (v "+typ+") MarshalJSON() ([]byte, error) {") + fmt.Fprintln(g.out, " w := jwriter.Writer{}") + fmt.Fprintln(g.out, " "+fname+"(&w, v)") + fmt.Fprintln(g.out, " return w.Buffer.BuildBytes(), w.Error") + fmt.Fprintln(g.out, "}") + } + + fmt.Fprintln(g.out, "// MarshalEasyJSON supports easyjson.Marshaler interface") + fmt.Fprintln(g.out, "func (v "+typ+") MarshalEasyJSON(w *jwriter.Writer) {") + fmt.Fprintln(g.out, " "+fname+"(w, v)") + fmt.Fprintln(g.out, "}") + + return nil +} -- cgit v1.2.3-1-g7c22