github.com/anonymouse64/snapd@v0.0.0-20210824153203-04c4c42d842d/interfaces/utils/utils.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2018 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package utils 21 22 import ( 23 "encoding/json" 24 ) 25 26 // NormalizeInterfaceAttributes normalises types of an attribute values. 27 // The following transformations are applied: int -> int64, float32 -> float64. 28 // The normalisation proceeds recursively through maps and slices. 29 func NormalizeInterfaceAttributes(value interface{}) interface{} { 30 // Normalize ints/floats using their 64-bit variants. 31 switch v := value.(type) { 32 case int: 33 return int64(v) 34 case float32: 35 return float64(v) 36 case []interface{}: 37 vc := make([]interface{}, len(v)) 38 for i, el := range v { 39 vc[i] = NormalizeInterfaceAttributes(el) 40 } 41 return vc 42 case map[string]interface{}: 43 vc := make(map[string]interface{}, len(v)) 44 for key, item := range v { 45 vc[key] = NormalizeInterfaceAttributes(item) 46 } 47 return vc 48 case json.Number: 49 jsonval := value.(json.Number) 50 if asInt, err := jsonval.Int64(); err == nil { 51 return asInt 52 } 53 asFloat, _ := jsonval.Float64() 54 return asFloat 55 } 56 return value 57 } 58 59 // CopyAttributes makes a deep copy of the attributes map. 60 func CopyAttributes(value map[string]interface{}) map[string]interface{} { 61 return copyRecursive(value).(map[string]interface{}) 62 } 63 64 func copyRecursive(value interface{}) interface{} { 65 // note: ensure all the mutable types (or types that need a conversion) 66 // are handled here. 67 switch v := value.(type) { 68 case []interface{}: 69 arr := make([]interface{}, len(v)) 70 for i, el := range v { 71 arr[i] = copyRecursive(el) 72 } 73 return arr 74 case map[string]interface{}: 75 mp := make(map[string]interface{}, len(v)) 76 for key, item := range v { 77 mp[key] = copyRecursive(item) 78 } 79 return mp 80 } 81 return value 82 }