github.com/mitranim/gg@v0.1.17/zop.go (about) 1 package gg 2 3 /* 4 Short for "zero optional value". Workaround for the lack of type inference in 5 struct literals. 6 */ 7 func ZopVal[A any](val A) Zop[A] { return Zop[A]{val} } 8 9 /* 10 Short for "zero optional". The zero value is considered empty/null in JSON. Note 11 that "encoding/json" doesn't support ",omitempty" for structs. This wrapper 12 allows empty structs to become "null". This type doesn't implement any other 13 encoding or decoding methods, and is intended only for non-scalar values such 14 as "models" / "data classes". 15 */ 16 type Zop[A any] struct { 17 /** 18 Annotation `role:"ref"` indicates that this field is a reference/pointer to 19 the inner type/value. Reflection-based code may use this to treat this type 20 like a pointer. 21 */ 22 Val A `role:"ref"` 23 } 24 25 // Implement `Nullable`. True if zero value of its type. 26 func (self Zop[_]) IsNull() bool { return IsZero(self.Val) } 27 28 // Inverse of `.IsNull`. 29 func (self Zop[_]) IsNotNull() bool { return !IsZero(self.Val) } 30 31 // Implement `Clearer`. Zeroes the receiver. 32 func (self *Zop[_]) Clear() { PtrClear(&self.Val) } 33 34 // Implement `Getter`, returning the underlying value as-is. 35 func (self Zop[A]) Get() A { return self.Val } 36 37 // Implement `Setter`, modifying the underlying value. 38 func (self *Zop[A]) Set(val A) { self.Val = val } 39 40 // Implement `Ptrer`, returning a pointer to the underlying value. 41 func (self *Zop[A]) Ptr() *A { 42 if self == nil { 43 return nil 44 } 45 return &self.Val 46 } 47 48 /* 49 Implement `json.Marshaler`. If `.IsNull`, returns a representation of JSON null. 50 Otherwise uses `json.Marshal` to encode the underlying value. 51 */ 52 func (self Zop[A]) MarshalJSON() ([]byte, error) { 53 return JsonBytesNullCatch[A](self) 54 } 55 56 /* 57 Implement `json.Unmarshaler`. If the input is empty or represents JSON null, 58 clears the receiver via `.Clear`. Otherwise uses `JsonParseCatch` to decode 59 into the underlying value. 60 */ 61 func (self *Zop[A]) UnmarshalJSON(src []byte) error { 62 if IsJsonEmpty(src) { 63 self.Clear() 64 return nil 65 } 66 return JsonParseCatch(src, &self.Val) 67 } 68 69 /* 70 FP-style "mapping". If the original value is zero, or if the function is nil, 71 the output is zero. Otherwise the output is the result of calling the function 72 with the previous value. 73 */ 74 func ZopMap[A, B any](src Zop[A], fun func(A) B) (out Zop[B]) { 75 if src.IsNotNull() && fun != nil { 76 out.Val = fun(src.Val) 77 } 78 return 79 }