Support integer type as map key

This commit is contained in:
Chuntao Lu
2017-10-19 19:41:26 -07:00
parent 3fd5e860b6
commit 06d7c00bd4
4 changed files with 43 additions and 26 deletions
+16 -13
View File
@@ -36,16 +36,18 @@ var primitiveDecoders = map[reflect.Kind]string{
}
var primitiveStringDecoders = map[reflect.Kind]string{
reflect.Int: "in.IntStr()",
reflect.Int8: "in.Int8Str()",
reflect.Int16: "in.Int16Str()",
reflect.Int32: "in.Int32Str()",
reflect.Int64: "in.Int64Str()",
reflect.Uint: "in.UintStr()",
reflect.Uint8: "in.Uint8Str()",
reflect.Uint16: "in.Uint16Str()",
reflect.Uint32: "in.Uint32Str()",
reflect.Uint64: "in.Uint64Str()",
reflect.String: "in.String()",
reflect.Int: "in.IntStr()",
reflect.Int8: "in.Int8Str()",
reflect.Int16: "in.Int16Str()",
reflect.Int32: "in.Int32Str()",
reflect.Int64: "in.Int64Str()",
reflect.Uint: "in.UintStr()",
reflect.Uint8: "in.Uint8Str()",
reflect.Uint16: "in.Uint16Str()",
reflect.Uint32: "in.Uint32Str()",
reflect.Uint64: "in.Uint64Str()",
reflect.Uintptr: "in.UintptrStr()",
}
// genTypeDecoder generates decoding code for the type t, but uses unmarshaler interface if implemented by t.
@@ -198,8 +200,9 @@ func (g *Generator) genTypeDecoderNoCheck(t reflect.Type, out string, tags field
case reflect.Map:
key := t.Key()
if key.Kind() != reflect.String {
return fmt.Errorf("map type %v not supported: only string keys are allowed", key)
keyDec, ok := primitiveStringDecoders[key.Kind()]
if !ok {
return fmt.Errorf("map type %v not supported: only string and integer keys are allowed", key)
}
elem := t.Elem()
tmpVar := g.uniqueVarName()
@@ -215,7 +218,7 @@ func (g *Generator) genTypeDecoderNoCheck(t reflect.Type, out string, tags field
fmt.Fprintln(g.out, ws+" }")
fmt.Fprintln(g.out, ws+" for !in.IsDelim('}') {")
fmt.Fprintln(g.out, ws+" key := "+g.getType(t.Key())+"(in.String())")
fmt.Fprintln(g.out, ws+" key := "+g.getType(key)+"("+keyDec+")")
fmt.Fprintln(g.out, ws+" in.WantColon()")
fmt.Fprintln(g.out, ws+" var "+tmpVar+" "+g.getType(elem))
+16 -13
View File
@@ -33,16 +33,18 @@ var primitiveEncoders = map[reflect.Kind]string{
}
var primitiveStringEncoders = map[reflect.Kind]string{
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.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.
@@ -186,8 +188,9 @@ func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldT
case reflect.Map:
key := t.Key()
if key.Kind() != reflect.String {
return fmt.Errorf("map type %v not supported: only string keys are allowed", 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()
@@ -199,7 +202,7 @@ func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldT
fmt.Fprintln(g.out, ws+" for "+tmpVar+"Name, "+tmpVar+"Value := range "+in+" {")
fmt.Fprintln(g.out, ws+" if !"+tmpVar+"First { out.RawByte(',') }")
fmt.Fprintln(g.out, ws+" "+tmpVar+"First = false")
fmt.Fprintln(g.out, ws+" out.String(string("+tmpVar+"Name))")
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); err != nil {
+4
View File
@@ -903,6 +903,10 @@ func (r *Lexer) UintStr() uint {
return uint(r.Uint64Str())
}
func (r *Lexer) UintptrStr() uintptr {
return uintptr(r.Uint64Str())
}
func (r *Lexer) Int8Str() int8 {
s, b := r.unsafeString()
if !r.Ok() {
+7
View File
@@ -196,6 +196,13 @@ func (w *Writer) Uint64Str(n uint64) {
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}
func (w *Writer) UintptrStr(n uintptr) {
w.Buffer.EnsureSpace(20)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}
func (w *Writer) Int8Str(n int8) {
w.Buffer.EnsureSpace(4)
w.Buffer.Buf = append(w.Buffer.Buf, '"')