1// Copyright 2014 Google Inc. 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// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package proptools 16 17import ( 18 "reflect" 19 "strings" 20 "unicode" 21 "unicode/utf8" 22) 23 24// PropertyNameForField converts the name of a field in property struct to the property name that 25// might appear in a Blueprints file. Since the property struct fields must always be exported 26// to be accessed with reflection and the canonical Blueprints style is lowercased names, it 27// lower cases the first rune in the field name unless the field name contains an uppercase rune 28// after the first rune (which is always uppercase), and no lowercase runes. 29func PropertyNameForField(fieldName string) string { 30 r, size := utf8.DecodeRuneInString(fieldName) 31 propertyName := string(unicode.ToLower(r)) 32 if size == len(fieldName) { 33 return propertyName 34 } 35 if strings.IndexFunc(fieldName[size:], unicode.IsLower) == -1 && 36 strings.IndexFunc(fieldName[size:], unicode.IsUpper) != -1 { 37 return fieldName 38 } 39 if len(fieldName) > size { 40 propertyName += fieldName[size:] 41 } 42 return propertyName 43} 44 45// FieldNameForProperty converts the name of a property that might appear in a Blueprints file to 46// the name of a field in property struct by uppercasing the first rune. 47func FieldNameForProperty(propertyName string) string { 48 r, size := utf8.DecodeRuneInString(propertyName) 49 fieldName := string(unicode.ToUpper(r)) 50 if len(propertyName) > size { 51 fieldName += propertyName[size:] 52 } 53 return fieldName 54} 55 56// Clear takes a pointer to a field and clears the value pointed to by the pointer with zero value. 57func Clear[T any](ptr *T) { 58 var zeroValue T 59 *ptr = zeroValue 60} 61 62// BoolPtr returns a pointer to a new bool containing the given value. 63func BoolPtr(b bool) *bool { 64 return &b 65} 66 67// Int64Ptr returns a pointer to a new int64 containing the given value. 68func Int64Ptr(i int64) *int64 { 69 b := int64(i) 70 return &(b) 71} 72 73// StringPtr returns a pointer to a new string containing the given value. 74func StringPtr(s string) *string { 75 return &s 76} 77 78// BoolDefault takes a pointer to a bool and returns the value pointed to by the pointer if it is non-nil, 79// or def if the pointer is nil. 80func BoolDefault(b *bool, def bool) bool { 81 if b != nil { 82 return *b 83 } 84 return def 85} 86 87// Bool takes a pointer to a bool and returns true iff the pointer is non-nil and points to a true 88// value. 89func Bool(b *bool) bool { 90 return BoolDefault(b, false) 91} 92 93// String takes a pointer to a string and returns the value of the string if the pointer is non-nil, 94// or def if the pointer is nil. 95func StringDefault(s *string, def string) string { 96 if s != nil { 97 return *s 98 } 99 return def 100} 101 102// String takes a pointer to a string and returns the value of the string if the pointer is non-nil, 103// or an empty string. 104func String(s *string) string { 105 return StringDefault(s, "") 106} 107 108// Slice takes a pointer to a slice and returns the value of the slice if the pointer is non-nil, 109// or a nil slice. 110func Slice[T any](s *[]T) []T { 111 if s != nil { 112 return *s 113 } 114 return nil 115} 116 117// IntDefault takes a pointer to an int64 and returns the value pointed to by the pointer cast to int 118// if it is non-nil, or def if the pointer is nil. 119func IntDefault(i *int64, def int) int { 120 if i != nil { 121 return int(*i) 122 } 123 return def 124} 125 126// Int takes a pointer to an int64 and returns the value pointed to by the pointer cast to int 127// if it is non-nil, or 0 if the pointer is nil. 128func Int(i *int64) int { 129 return IntDefault(i, 0) 130} 131 132func isStruct(t reflect.Type) bool { 133 return t.Kind() == reflect.Struct 134} 135 136func isStructPtr(t reflect.Type) bool { 137 return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct 138} 139 140func isSlice(t reflect.Type) bool { 141 return t.Kind() == reflect.Slice 142} 143 144func isSliceOfStruct(t reflect.Type) bool { 145 return isSlice(t) && isStruct(t.Elem()) 146} 147 148func isStringOrStringPtr(t reflect.Type) bool { 149 return t.Kind() == reflect.String || (t.Kind() == reflect.Pointer && t.Elem().Kind() == reflect.String) 150} 151 152func isMapOfStruct(t reflect.Type) bool { 153 return t.Kind() == reflect.Map && isStruct(t.Elem()) 154} 155 156func isConfigurable(t reflect.Type) bool { 157 return isStruct(t) && t.NumField() > 0 && typeFields(t)[0].Type == configurableMarkerType 158} 159 160func IsConfigurable(t reflect.Type) bool { 161 return isConfigurable(t) 162} 163