1 package ldvalue 2 3 // OptionalString represents a string that may or may not have a value. This is similar to using a 4 // string pointer to distinguish between an empty string and nil, but it is safer because it does 5 // not expose a pointer to any mutable value. 6 // 7 // Unlike [Value], which can contain a value of any JSON-compatible type, OptionalString either 8 // contains a string or nothing. To create an instance with a string value, use [NewOptionalString]. 9 // There is no corresponding method for creating an instance with no value; simply use the empty 10 // literal OptionalString{}. 11 // 12 // os1 := NewOptionalString("this has a value") 13 // os2 := NewOptionalString("") // this has a value which is an empty string 14 // os2 := OptionalString{} // this does not have a value 15 // 16 // This can also be used as a convenient way to construct a string pointer within an expression. 17 // For instance, this example causes myStringPointer to point to the string "x": 18 // 19 // var myStringPointer *string = NewOptionalString("x").AsPointer() 20 // 21 // The reason LaunchDarkly code uses this specific type instead of a generic Optional[T] is for 22 // efficiency in JSON marshaling/unmarshaling. A generic type would have to use reflection and 23 // dynamic typecasting for its marshal/unmarshal methods. 24 type OptionalString struct { 25 optValue optional[string] 26 } 27 28 // NewOptionalString constructs an OptionalString that has a string value. 29 // 30 // There is no corresponding method for creating an OptionalString with no value; simply use 31 // the empty literal OptionalString{}. 32 func NewOptionalString(value string) OptionalString { 33 return OptionalString{optValue: newOptional(value)} 34 } 35 36 // NewOptionalStringFromPointer constructs an OptionalString from a string pointer. If the pointer 37 // is non-nil, then the OptionalString copies its value; otherwise the OptionalString has no value. 38 func NewOptionalStringFromPointer(valuePointer *string) OptionalString { 39 return OptionalString{optValue: newOptionalFromPointer(valuePointer)} 40 } 41 42 // IsDefined returns true if the OptionalString contains a string value, or false if it has no value. 43 func (o OptionalString) IsDefined() bool { 44 return o.optValue.isDefined() 45 } 46 47 // StringValue returns the OptionalString's value, or an empty string if it has no value. 48 func (o OptionalString) StringValue() string { 49 return o.optValue.getOrZeroValue() 50 } 51 52 // Get is a combination of StringValue and IsDefined. If the OptionalString contains a string value, 53 // it returns that value and true; otherwise it returns an empty string and false. 54 func (o OptionalString) Get() (string, bool) { 55 return o.optValue.get() 56 } 57 58 // OrElse returns the OptionalString's value if it has one, or else the specified fallback value. 59 func (o OptionalString) OrElse(valueIfEmpty string) string { 60 return o.optValue.getOrElse(valueIfEmpty) 61 } 62 63 // OnlyIfNonEmptyString returns the same OptionalString unless it contains an empty string (""), in 64 // which case it returns an OptionalString that has no value. 65 func (o OptionalString) OnlyIfNonEmptyString() OptionalString { 66 if value, ok := o.optValue.get(); ok && value == "" { 67 return OptionalString{} 68 } 69 return o 70 } 71 72 // AsPointer returns the OptionalString's value as a string pointer if it has a value, or 73 // nil otherwise. 74 // 75 // The string value, if any, is copied rather than returning to a pointer to the internal field. 76 func (o OptionalString) AsPointer() *string { 77 return o.optValue.getAsPointer() 78 } 79 80 // AsValue converts the OptionalString to a [Value], which is either [Null]() or a string value. 81 func (o OptionalString) AsValue() Value { 82 if value, ok := o.optValue.get(); ok { 83 return String(value) 84 } 85 return Null() 86 } 87