| // Copyright (c) HashiCorp, Inc. |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| package dbplugin |
| |
| import ( |
| "encoding/json" |
| "math" |
| |
| "google.golang.org/protobuf/types/known/structpb" |
| ) |
| |
| func mapToStruct(m map[string]interface{}) (*structpb.Struct, error) { |
| // Convert any json.Number typed values to float64, since the |
| // type does not have a conversion mapping defined in structpb |
| for k, v := range m { |
| if n, ok := v.(json.Number); ok { |
| nf, err := n.Float64() |
| if err != nil { |
| return nil, err |
| } |
| |
| m[k] = nf |
| } |
| } |
| |
| return structpb.NewStruct(m) |
| } |
| |
| func structToMap(strct *structpb.Struct) map[string]interface{} { |
| m := strct.AsMap() |
| coerceFloatsToInt(m) |
| return m |
| } |
| |
| // coerceFloatsToInt if the floats can be coerced to an integer without losing data |
| func coerceFloatsToInt(m map[string]interface{}) { |
| for k, v := range m { |
| fVal, ok := v.(float64) |
| if !ok { |
| continue |
| } |
| if isInt(fVal) { |
| m[k] = int64(fVal) |
| } |
| } |
| } |
| |
| // isInt attempts to determine if the given floating point number could be represented as an integer without losing data |
| // This does not work for very large floats, however in this usage that's okay since we don't expect numbers that large. |
| func isInt(f float64) bool { |
| return math.Floor(f) == f |
| } |