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