github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/metautil/normalize.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016 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 metautil takes care of basic details of working with snap metadata formats.
    21  package metautil
    22  
    23  import (
    24  	"fmt"
    25  )
    26  
    27  // NormalizeValue validates values and returns a normalized version of it
    28  // (map[interface{}]interface{} is turned into map[string]interface{})
    29  func NormalizeValue(v interface{}) (interface{}, error) {
    30  	switch x := v.(type) {
    31  	case string:
    32  		return x, nil
    33  	case bool:
    34  		return x, nil
    35  	case int:
    36  		return int64(x), nil
    37  	case int64:
    38  		return x, nil
    39  	case float64:
    40  		return x, nil
    41  	case float32:
    42  		return float64(x), nil
    43  	case []interface{}:
    44  		l := make([]interface{}, len(x))
    45  		for i, el := range x {
    46  			el, err := NormalizeValue(el)
    47  			if err != nil {
    48  				return nil, err
    49  			}
    50  			l[i] = el
    51  		}
    52  		return l, nil
    53  	case map[interface{}]interface{}:
    54  		m := make(map[string]interface{}, len(x))
    55  		for k, item := range x {
    56  			kStr, ok := k.(string)
    57  			if !ok {
    58  				return nil, fmt.Errorf("non-string key: %v", k)
    59  			}
    60  			item, err := NormalizeValue(item)
    61  			if err != nil {
    62  				return nil, err
    63  			}
    64  			m[kStr] = item
    65  		}
    66  		return m, nil
    67  	case map[string]interface{}:
    68  		m := make(map[string]interface{}, len(x))
    69  		for k, item := range x {
    70  			item, err := NormalizeValue(item)
    71  			if err != nil {
    72  				return nil, err
    73  			}
    74  			m[k] = item
    75  		}
    76  		return m, nil
    77  	default:
    78  		return nil, fmt.Errorf("invalid scalar: %v", v)
    79  	}
    80  }