github.com/shohhei1126/hugo@v0.42.2-0.20180623210752-3d5928889ad7/tpl/collections/reflect_helpers.go (about) 1 // Copyright 2017 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package collections 15 16 import ( 17 "errors" 18 "fmt" 19 "reflect" 20 "time" 21 ) 22 23 var ( 24 zero reflect.Value 25 errorType = reflect.TypeOf((*error)(nil)).Elem() 26 timeType = reflect.TypeOf((*time.Time)(nil)).Elem() 27 ) 28 29 func numberToFloat(v reflect.Value) (float64, error) { 30 switch kind := v.Kind(); { 31 case isFloat(kind): 32 return v.Float(), nil 33 case isInt(kind): 34 return float64(v.Int()), nil 35 case isUint(kind): 36 return float64(v.Uint()), nil 37 case kind == reflect.Interface: 38 return numberToFloat(v.Elem()) 39 default: 40 return 0, fmt.Errorf("Invalid kind %s in numberToFloat", kind) 41 } 42 } 43 44 // There are potential overflows in this function, but the downconversion of 45 // int64 etc. into int8 etc. is coming from the synthetic unit tests for Union etc. 46 // TODO(bep) We should consider normalizing the slices to int64 etc. 47 func convertNumber(v reflect.Value, to reflect.Kind) (reflect.Value, error) { 48 var n reflect.Value 49 if isFloat(to) { 50 f, err := toFloat(v) 51 if err != nil { 52 return n, err 53 } 54 switch to { 55 case reflect.Float32: 56 n = reflect.ValueOf(float32(f)) 57 default: 58 n = reflect.ValueOf(float64(f)) 59 } 60 } else if isInt(to) { 61 i, err := toInt(v) 62 if err != nil { 63 return n, err 64 } 65 switch to { 66 case reflect.Int: 67 n = reflect.ValueOf(int(i)) 68 case reflect.Int8: 69 n = reflect.ValueOf(int8(i)) 70 case reflect.Int16: 71 n = reflect.ValueOf(int16(i)) 72 case reflect.Int32: 73 n = reflect.ValueOf(int32(i)) 74 case reflect.Int64: 75 n = reflect.ValueOf(int64(i)) 76 } 77 } else if isUint(to) { 78 i, err := toUint(v) 79 if err != nil { 80 return n, err 81 } 82 switch to { 83 case reflect.Uint: 84 n = reflect.ValueOf(uint(i)) 85 case reflect.Uint8: 86 n = reflect.ValueOf(uint8(i)) 87 case reflect.Uint16: 88 n = reflect.ValueOf(uint16(i)) 89 case reflect.Uint32: 90 n = reflect.ValueOf(uint32(i)) 91 case reflect.Uint64: 92 n = reflect.ValueOf(uint64(i)) 93 } 94 95 } 96 97 if !n.IsValid() { 98 return n, errors.New("invalid values") 99 } 100 101 return n, nil 102 103 } 104 105 func isNumber(kind reflect.Kind) bool { 106 return isInt(kind) || isUint(kind) || isFloat(kind) 107 } 108 109 func isInt(kind reflect.Kind) bool { 110 switch kind { 111 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 112 return true 113 default: 114 return false 115 } 116 } 117 118 func isUint(kind reflect.Kind) bool { 119 switch kind { 120 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 121 return true 122 default: 123 return false 124 } 125 } 126 127 func isFloat(kind reflect.Kind) bool { 128 switch kind { 129 case reflect.Float32, reflect.Float64: 130 return true 131 default: 132 return false 133 } 134 }