diff --git a/conv_go.go b/conv_go.go new file mode 100644 index 00000000..9f578c39 --- /dev/null +++ b/conv_go.go @@ -0,0 +1,11 @@ +//go:build !tinygo + +package yaml + +import ( + "reflect" +) + +func convertibleTo(src reflect.Value, typ reflect.Type) bool { + return src.Type().ConvertibleTo(typ) +} diff --git a/conv_tinygo.go b/conv_tinygo.go new file mode 100644 index 00000000..c26ffcde --- /dev/null +++ b/conv_tinygo.go @@ -0,0 +1,65 @@ +//go:build tinygo + +package yaml + +import ( + "reflect" +) + +func convertibleTo(src reflect.Value, typ reflect.Type) bool { + srck, typk := src.Kind(), typ.Kind() + if srck == typk { + return true + } + switch srck { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + switch typk { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return true + case reflect.Float32, reflect.Float64: + return true + case reflect.String: + return true + } + + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + switch typk { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return true + case reflect.Float32, reflect.Float64: + return true + case reflect.String: + return true + } + + case reflect.Float32, reflect.Float64: + switch typk { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return true + case reflect.Float32, reflect.Float64: + return true + } + + case reflect.Slice: + if typk == reflect.String /*&& !src.Type().Elem().isNamed()*/ { + switch src.Type().Elem().Kind() { + case reflect.Uint8, reflect.Int32: + return true + } + } + + case reflect.String: + switch typk { + case reflect.Slice: + switch typ.Elem().Kind() { + case reflect.Uint8, reflect.Int32: + return true + } + return false + } + } + + return false +} diff --git a/decode.go b/decode.go index fe990e54..0cad76b8 100644 --- a/decode.go +++ b/decode.go @@ -582,7 +582,7 @@ func (d *Decoder) getArrayNode(node ast.Node) (ast.ArrayNode, error) { func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type, src ast.Node) (reflect.Value, error) { if typ.Kind() != reflect.String { - if !v.Type().ConvertibleTo(typ) { + if !convertibleTo(v, typ) { // Special case for "strings -> floats" aka scientific notation // If the destination type is a float and the source type is a string, check if we can @@ -613,7 +613,7 @@ func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type, src ast.Node) case reflect.Bool: return reflect.ValueOf(fmt.Sprint(v.Bool())), nil } - if !v.Type().ConvertibleTo(typ) { + if !convertibleTo(v, typ) { return reflect.Zero(typ), errors.ErrTypeMismatch(typ, v.Type(), src.GetToken()) } return v.Convert(typ), nil @@ -868,9 +868,7 @@ func (d *Decoder) decodeByUnmarshaler(ctx context.Context, dst reflect.Value, sr return fmt.Errorf("does not implemented Unmarshaler") } -var ( - astNodeType = reflect.TypeOf((*ast.Node)(nil)).Elem() -) +var astNodeType = reflect.TypeOf((*ast.Node)(nil)).Elem() func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.Node) error { if src.Type() == ast.AnchorType { @@ -1634,7 +1632,7 @@ func (d *Decoder) decodeMap(ctx context.Context, dst reflect.Value, src ast.Node return err } k = reflect.ValueOf(keyVal) - if k.IsValid() && k.Type().ConvertibleTo(keyType) { + if k.IsValid() && convertibleTo(k, keyType) { k = k.Convert(keyType) } }