Colin Cross | 8e0c511 | 2015-01-23 14:15:10 -0800 | [diff] [blame] | 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 | |
Jamie Gennis | b9cbdae | 2014-10-02 18:36:13 -0700 | [diff] [blame] | 15 | package proptools |
| 16 | |
| 17 | import ( |
Colin Cross | 6898d26 | 2020-01-27 16:48:30 -0800 | [diff] [blame] | 18 | "reflect" |
Colin Cross | 3bbbdf3 | 2020-02-05 13:45:11 -0800 | [diff] [blame] | 19 | "strings" |
Jamie Gennis | b9cbdae | 2014-10-02 18:36:13 -0700 | [diff] [blame] | 20 | "unicode" |
| 21 | "unicode/utf8" |
| 22 | ) |
| 23 | |
Colin Cross | 3bbbdf3 | 2020-02-05 13:45:11 -0800 | [diff] [blame] | 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 |
Colin Cross | fc6efcb | 2020-02-05 17:10:18 -0800 | [diff] [blame] | 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. |
Jamie Gennis | b9cbdae | 2014-10-02 18:36:13 -0700 | [diff] [blame] | 29 | func PropertyNameForField(fieldName string) string { |
| 30 | r, size := utf8.DecodeRuneInString(fieldName) |
| 31 | propertyName := string(unicode.ToLower(r)) |
Colin Cross | 3bbbdf3 | 2020-02-05 13:45:11 -0800 | [diff] [blame] | 32 | if size == len(fieldName) { |
| 33 | return propertyName |
| 34 | } |
Colin Cross | fc6efcb | 2020-02-05 17:10:18 -0800 | [diff] [blame] | 35 | if strings.IndexFunc(fieldName[size:], unicode.IsLower) == -1 && |
| 36 | strings.IndexFunc(fieldName[size:], unicode.IsUpper) != -1 { |
Colin Cross | 3bbbdf3 | 2020-02-05 13:45:11 -0800 | [diff] [blame] | 37 | return fieldName |
| 38 | } |
Jamie Gennis | b9cbdae | 2014-10-02 18:36:13 -0700 | [diff] [blame] | 39 | if len(fieldName) > size { |
| 40 | propertyName += fieldName[size:] |
| 41 | } |
| 42 | return propertyName |
| 43 | } |
| 44 | |
Colin Cross | 3bbbdf3 | 2020-02-05 13:45:11 -0800 | [diff] [blame] | 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. |
Colin Cross | 4572edd | 2015-05-13 14:36:24 -0700 | [diff] [blame] | 47 | func 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 | |
Colin Cross | 8011768 | 2015-10-30 15:53:55 -0700 | [diff] [blame] | 56 | // BoolPtr returns a pointer to a new bool containing the given value. |
| 57 | func BoolPtr(b bool) *bool { |
| 58 | return &b |
| 59 | } |
| 60 | |
Nan Zhang | f586544 | 2017-11-01 14:03:28 -0700 | [diff] [blame] | 61 | // Int64Ptr returns a pointer to a new int64 containing the given value. |
| 62 | func Int64Ptr(i int64) *int64 { |
| 63 | b := int64(i) |
| 64 | return &(b) |
| 65 | } |
| 66 | |
Colin Cross | 8011768 | 2015-10-30 15:53:55 -0700 | [diff] [blame] | 67 | // StringPtr returns a pointer to a new string containing the given value. |
| 68 | func StringPtr(s string) *string { |
| 69 | return &s |
| 70 | } |
| 71 | |
Colin Cross | de3ef3a | 2018-04-10 14:53:40 -0700 | [diff] [blame] | 72 | // BoolDefault takes a pointer to a bool and returns the value pointed to by the pointer if it is non-nil, |
| 73 | // or def if the pointer is nil. |
| 74 | func BoolDefault(b *bool, def bool) bool { |
Colin Cross | 8011768 | 2015-10-30 15:53:55 -0700 | [diff] [blame] | 75 | if b != nil { |
| 76 | return *b |
| 77 | } |
Colin Cross | de3ef3a | 2018-04-10 14:53:40 -0700 | [diff] [blame] | 78 | return def |
| 79 | } |
| 80 | |
| 81 | // Bool takes a pointer to a bool and returns true iff the pointer is non-nil and points to a true |
| 82 | // value. |
| 83 | func Bool(b *bool) bool { |
| 84 | return BoolDefault(b, false) |
| 85 | } |
| 86 | |
| 87 | // String takes a pointer to a string and returns the value of the string if the pointer is non-nil, |
| 88 | // or def if the pointer is nil. |
| 89 | func StringDefault(s *string, def string) string { |
| 90 | if s != nil { |
| 91 | return *s |
| 92 | } |
| 93 | return def |
Colin Cross | 8011768 | 2015-10-30 15:53:55 -0700 | [diff] [blame] | 94 | } |
| 95 | |
| 96 | // String takes a pointer to a string and returns the value of the string if the pointer is non-nil, |
| 97 | // or an empty string. |
| 98 | func String(s *string) string { |
Colin Cross | de3ef3a | 2018-04-10 14:53:40 -0700 | [diff] [blame] | 99 | return StringDefault(s, "") |
Colin Cross | 8011768 | 2015-10-30 15:53:55 -0700 | [diff] [blame] | 100 | } |
Colin Cross | 66c0b13 | 2019-09-25 11:25:04 -0700 | [diff] [blame] | 101 | |
| 102 | // IntDefault takes a pointer to an int64 and returns the value pointed to by the pointer cast to int |
| 103 | // if it is non-nil, or def if the pointer is nil. |
| 104 | func IntDefault(i *int64, def int) int { |
| 105 | if i != nil { |
| 106 | return int(*i) |
| 107 | } |
| 108 | return def |
| 109 | } |
| 110 | |
| 111 | // Int takes a pointer to an int64 and returns the value pointed to by the pointer cast to int |
| 112 | // if it is non-nil, or 0 if the pointer is nil. |
| 113 | func Int(i *int64) int { |
| 114 | return IntDefault(i, 0) |
| 115 | } |
Colin Cross | 6898d26 | 2020-01-27 16:48:30 -0800 | [diff] [blame] | 116 | |
| 117 | func isStruct(t reflect.Type) bool { |
| 118 | return t.Kind() == reflect.Struct |
| 119 | } |
| 120 | |
| 121 | func isStructPtr(t reflect.Type) bool { |
| 122 | return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct |
| 123 | } |
Sasha Smundak | 29fdcad | 2020-02-11 22:39:47 -0800 | [diff] [blame] | 124 | |
| 125 | func isSlice(t reflect.Type) bool { |
| 126 | return t.Kind() == reflect.Slice |
| 127 | } |