Support int and uint types as map key type

This commit is contained in:
Masaaki Goshima 2020-12-12 18:09:46 +09:00
parent 699ab766f5
commit 85577616f8
5 changed files with 4376 additions and 853 deletions

View File

@ -214,6 +214,8 @@ func (t opType) fieldToStringTagField() opType {
"uint", "uint8", "uint16", "uint32", "uint64", "uint", "uint8", "uint16", "uint32", "uint64",
"float32", "float64", "bool", "string", "bytes", "float32", "float64", "bool", "string", "bytes",
"array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText", "recursive", "array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText", "recursive",
"intString", "int8String", "int16String", "int32String", "int64String",
"uintString", "uint8String", "uint16String", "uint32String", "uint64String",
} }
primitiveTypesUpper := []string{} primitiveTypesUpper := []string{}
for _, typ := range primitiveTypes { for _, typ := range primitiveTypes {

View File

@ -75,6 +75,27 @@ func (d *Decoder) compile(typ *rtype, structName, fieldName string) (decoder, er
return nil, &UnsupportedTypeError{Type: rtype2type(typ)} return nil, &UnsupportedTypeError{Type: rtype2type(typ)}
} }
func (d *Decoder) compileMapKey(typ *rtype, structName, fieldName string) (decoder, error) {
dec, err := d.compile(typ, structName, fieldName)
if err != nil {
return nil, err
}
for {
switch t := dec.(type) {
case *stringDecoder, *interfaceDecoder, *unmarshalJSONDecoder, *unmarshalTextDecoder:
return dec, nil
case *boolDecoder, *intDecoder, *uintDecoder, *numberDecoder:
return newWrappedStringDecoder(dec, structName, fieldName), nil
case *ptrDecoder:
dec = t.dec
default:
goto ERROR
}
}
ERROR:
return nil, &UnsupportedTypeError{Type: rtype2type(typ)}
}
func (d *Decoder) compilePtr(typ *rtype, structName, fieldName string) (decoder, error) { func (d *Decoder) compilePtr(typ *rtype, structName, fieldName string) (decoder, error) {
dec, err := d.compile(typ.Elem(), structName, fieldName) dec, err := d.compile(typ.Elem(), structName, fieldName)
if err != nil { if err != nil {
@ -186,7 +207,7 @@ func (d *Decoder) compileArray(typ *rtype, structName, fieldName string) (decode
} }
func (d *Decoder) compileMap(typ *rtype, structName, fieldName string) (decoder, error) { func (d *Decoder) compileMap(typ *rtype, structName, fieldName string) (decoder, error) {
keyDec, err := d.compile(typ.Key(), structName, fieldName) keyDec, err := d.compileMapKey(typ.Key(), structName, fieldName)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -129,6 +129,26 @@ func (e *Encoder) compileKey(ctx *encodeCompileContext) (*opcode, error) {
return e.compileInterface(ctx) return e.compileInterface(ctx)
case reflect.String: case reflect.String:
return e.compileString(ctx) return e.compileString(ctx)
case reflect.Int:
return e.compileIntString(ctx)
case reflect.Int8:
return e.compileInt8String(ctx)
case reflect.Int16:
return e.compileInt16String(ctx)
case reflect.Int32:
return e.compileInt32String(ctx)
case reflect.Int64:
return e.compileInt64String(ctx)
case reflect.Uint:
return e.compileUintString(ctx)
case reflect.Uint8:
return e.compileUint8String(ctx)
case reflect.Uint16:
return e.compileUint16String(ctx)
case reflect.Uint32:
return e.compileUint32String(ctx)
case reflect.Uint64:
return e.compileUint64String(ctx)
} }
return nil, &UnsupportedTypeError{Type: rtype2type(typ)} return nil, &UnsupportedTypeError{Type: rtype2type(typ)}
} }
@ -238,6 +258,66 @@ func (e *Encoder) compileUint64(ctx *encodeCompileContext) (*opcode, error) {
return code, nil return code, nil
} }
func (e *Encoder) compileIntString(ctx *encodeCompileContext) (*opcode, error) {
code := newOpCode(ctx, opIntString)
ctx.incIndex()
return code, nil
}
func (e *Encoder) compileInt8String(ctx *encodeCompileContext) (*opcode, error) {
code := newOpCode(ctx, opInt8String)
ctx.incIndex()
return code, nil
}
func (e *Encoder) compileInt16String(ctx *encodeCompileContext) (*opcode, error) {
code := newOpCode(ctx, opInt16String)
ctx.incIndex()
return code, nil
}
func (e *Encoder) compileInt32String(ctx *encodeCompileContext) (*opcode, error) {
code := newOpCode(ctx, opInt32String)
ctx.incIndex()
return code, nil
}
func (e *Encoder) compileInt64String(ctx *encodeCompileContext) (*opcode, error) {
code := newOpCode(ctx, opInt64String)
ctx.incIndex()
return code, nil
}
func (e *Encoder) compileUintString(ctx *encodeCompileContext) (*opcode, error) {
code := newOpCode(ctx, opUintString)
ctx.incIndex()
return code, nil
}
func (e *Encoder) compileUint8String(ctx *encodeCompileContext) (*opcode, error) {
code := newOpCode(ctx, opUint8String)
ctx.incIndex()
return code, nil
}
func (e *Encoder) compileUint16String(ctx *encodeCompileContext) (*opcode, error) {
code := newOpCode(ctx, opUint16String)
ctx.incIndex()
return code, nil
}
func (e *Encoder) compileUint32String(ctx *encodeCompileContext) (*opcode, error) {
code := newOpCode(ctx, opUint32String)
ctx.incIndex()
return code, nil
}
func (e *Encoder) compileUint64String(ctx *encodeCompileContext) (*opcode, error) {
code := newOpCode(ctx, opUint64String)
ctx.incIndex()
return code, nil
}
func (e *Encoder) compileFloat32(ctx *encodeCompileContext) (*opcode, error) { func (e *Encoder) compileFloat32(ctx *encodeCompileContext) (*opcode, error) {
code := newOpCode(ctx, opFloat32) code := newOpCode(ctx, opFloat32)
ctx.incIndex() ctx.incIndex()

File diff suppressed because it is too large Load Diff

View File

@ -143,6 +143,86 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
e.encodeUint64(e.ptrToUint64(load(ctxptr, code.idx))) e.encodeUint64(e.ptrToUint64(load(ctxptr, code.idx)))
e.encodeBytes([]byte{',', '\n'}) e.encodeBytes([]byte{',', '\n'})
code = code.next code = code.next
case opIntString:
e.encodeString(fmt.Sprint(e.ptrToInt(load(ctxptr, code.idx))))
e.encodeByte(',')
code = code.next
case opIntStringIndent:
e.encodeString(fmt.Sprint(e.ptrToInt(load(ctxptr, code.idx))))
e.encodeBytes([]byte{',', '\n'})
code = code.next
case opInt8String:
e.encodeString(fmt.Sprint(e.ptrToInt8(load(ctxptr, code.idx))))
e.encodeByte(',')
code = code.next
case opInt8StringIndent:
e.encodeString(fmt.Sprint(e.ptrToInt8(load(ctxptr, code.idx))))
e.encodeBytes([]byte{',', '\n'})
code = code.next
case opInt16String:
e.encodeString(fmt.Sprint(e.ptrToInt16(load(ctxptr, code.idx))))
e.encodeByte(',')
code = code.next
case opInt16StringIndent:
e.encodeString(fmt.Sprint(e.ptrToInt16(load(ctxptr, code.idx))))
e.encodeBytes([]byte{',', '\n'})
code = code.next
case opInt32String:
e.encodeString(fmt.Sprint(e.ptrToInt32(load(ctxptr, code.idx))))
e.encodeByte(',')
code = code.next
case opInt32StringIndent:
e.encodeString(fmt.Sprint(e.ptrToInt32(load(ctxptr, code.idx))))
e.encodeBytes([]byte{',', '\n'})
code = code.next
case opInt64String:
e.encodeString(fmt.Sprint(e.ptrToInt64(load(ctxptr, code.idx))))
e.encodeByte(',')
code = code.next
case opInt64StringIndent:
e.encodeString(fmt.Sprint(e.ptrToInt64(load(ctxptr, code.idx))))
e.encodeBytes([]byte{',', '\n'})
code = code.next
case opUintString:
e.encodeString(fmt.Sprint(e.ptrToUint(load(ctxptr, code.idx))))
e.encodeByte(',')
code = code.next
case opUintStringIndent:
e.encodeString(fmt.Sprint(e.ptrToUint(load(ctxptr, code.idx))))
e.encodeBytes([]byte{',', '\n'})
code = code.next
case opUint8String:
e.encodeString(fmt.Sprint(e.ptrToUint8(load(ctxptr, code.idx))))
e.encodeByte(',')
code = code.next
case opUint8StringIndent:
e.encodeString(fmt.Sprint(e.ptrToUint8(load(ctxptr, code.idx))))
e.encodeBytes([]byte{',', '\n'})
code = code.next
case opUint16String:
e.encodeString(fmt.Sprint(e.ptrToUint16(load(ctxptr, code.idx))))
e.encodeByte(',')
code = code.next
case opUint16StringIndent:
e.encodeString(fmt.Sprint(e.ptrToUint16(load(ctxptr, code.idx))))
e.encodeBytes([]byte{',', '\n'})
code = code.next
case opUint32String:
e.encodeString(fmt.Sprint(e.ptrToUint32(load(ctxptr, code.idx))))
e.encodeByte(',')
code = code.next
case opUint32StringIndent:
e.encodeString(fmt.Sprint(e.ptrToUint32(load(ctxptr, code.idx))))
e.encodeBytes([]byte{',', '\n'})
code = code.next
case opUint64String:
e.encodeString(fmt.Sprint(e.ptrToUint64(load(ctxptr, code.idx))))
e.encodeByte(',')
code = code.next
case opUint64StringIndent:
e.encodeString(fmt.Sprint(e.ptrToUint64(load(ctxptr, code.idx))))
e.encodeBytes([]byte{',', '\n'})
code = code.next
case opFloat32: case opFloat32:
e.encodeFloat32(e.ptrToFloat32(load(ctxptr, code.idx))) e.encodeFloat32(e.ptrToFloat32(load(ctxptr, code.idx)))
e.encodeByte(',') e.encodeByte(',')