mirror of
https://github.com/token2/snapd.git
synced 2026-03-13 11:15:47 -07:00
* ifstate: fix decoding of json numbers When we read the static slots/plugs from the state we decode them as with the default json decoding. This leads to float64 instead of the expected int. This PR fixes it and adds tests. It also adds support in NormalizeInterfaceAttributes for json.Number.
83 lines
2.3 KiB
Go
83 lines
2.3 KiB
Go
// -*- Mode: Go; indent-tabs-mode: t -*-
|
|
|
|
/*
|
|
* Copyright (C) 2018 Canonical Ltd
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 3 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
package utils
|
|
|
|
import (
|
|
"encoding/json"
|
|
)
|
|
|
|
// NormalizeInterfaceAttributes normalises types of an attribute values.
|
|
// The following transformations are applied: int -> int64, float32 -> float64.
|
|
// The normalisation proceeds recursively through maps and slices.
|
|
func NormalizeInterfaceAttributes(value interface{}) interface{} {
|
|
// Normalize ints/floats using their 64-bit variants.
|
|
switch v := value.(type) {
|
|
case int:
|
|
return int64(v)
|
|
case float32:
|
|
return float64(v)
|
|
case []interface{}:
|
|
vc := make([]interface{}, len(v))
|
|
for i, el := range v {
|
|
vc[i] = NormalizeInterfaceAttributes(el)
|
|
}
|
|
return vc
|
|
case map[string]interface{}:
|
|
vc := make(map[string]interface{}, len(v))
|
|
for key, item := range v {
|
|
vc[key] = NormalizeInterfaceAttributes(item)
|
|
}
|
|
return vc
|
|
case json.Number:
|
|
jsonval := value.(json.Number)
|
|
if asInt, err := jsonval.Int64(); err == nil {
|
|
return asInt
|
|
}
|
|
asFloat, _ := jsonval.Float64()
|
|
return asFloat
|
|
}
|
|
return value
|
|
}
|
|
|
|
// CopyAttributes makes a deep copy of the attributes map.
|
|
func CopyAttributes(value map[string]interface{}) map[string]interface{} {
|
|
return copyRecursive(value).(map[string]interface{})
|
|
}
|
|
|
|
func copyRecursive(value interface{}) interface{} {
|
|
// note: ensure all the mutable types (or types that need a conversion)
|
|
// are handled here.
|
|
switch v := value.(type) {
|
|
case []interface{}:
|
|
arr := make([]interface{}, len(v))
|
|
for i, el := range v {
|
|
arr[i] = copyRecursive(el)
|
|
}
|
|
return arr
|
|
case map[string]interface{}:
|
|
mp := make(map[string]interface{}, len(v))
|
|
for key, item := range v {
|
|
mp[key] = copyRecursive(item)
|
|
}
|
|
return mp
|
|
}
|
|
return value
|
|
}
|