Securing the open-source software supply chain
0

Configure Feed

Select the types of activity you want to include in your feed.

feat: Safety wrappers for optionals and pointers

Antonio Cheong (May 18, 2026, 9:49 PM +0100) fe4c0d8a f3370a84

+193
+80
pkg/common/safety/safety.go
··· 1 + package safety 2 + 3 + import "reflect" 4 + 5 + func isNil[T any](t T) bool { 6 + v := reflect.ValueOf(t) 7 + kind := v.Kind() 8 + // Must be one of these types to be nillable 9 + return (kind == reflect.Pointer || 10 + kind == reflect.Interface || 11 + kind == reflect.Slice || 12 + kind == reflect.Map || 13 + kind == reflect.Chan || 14 + kind == reflect.Func) && 15 + v.IsNil() 16 + } 17 + 18 + // Optional[T] represents a value that may or may not be present. It is the 19 + // safe equivalent of sql.NullString, sql.NullInt64, etc. — keeping DB 20 + // implementation details out of the domain layer. 21 + // 22 + // Use None[T]() for an absent value and Some(v) for a present one. 23 + type Optional[T any] struct { 24 + Value T 25 + Valid bool 26 + } 27 + 28 + // None returns an absent Optional[T]. 29 + func None[T any]() Optional[T] { 30 + return Optional[T]{} 31 + } 32 + 33 + // Some returns a present Optional[T] wrapping v. 34 + func Some[T any](v T) Optional[T] { 35 + if isNil(v) { 36 + panic("valid optional should never be nil") 37 + } 38 + return Optional[T]{Value: v, Valid: true} 39 + } 40 + 41 + // Get returns the underlying value and whether it is present. 42 + func (o Optional[T]) Get() (T, bool) { 43 + return o.Value, o.Valid 44 + } 45 + 46 + // Or returns the underlying value if present, otherwise the provided default. 47 + func (o Optional[T]) Or(def T) T { 48 + if o.Valid { 49 + return o.Value 50 + } 51 + return def 52 + } 53 + 54 + // Ptr[T] is a non-nullable pointer. Constructing one with a nil pointer panics, 55 + // making the non-null guarantee explicit and visible in the type itself — as 56 + // opposed to *T, which is silently nullable. 57 + // 58 + // Use MakePtr(v) to create one from a value, or NewPtr(p) from a pointer you 59 + // know to be non-nil. 60 + type Ptr[T any] struct { 61 + v *T 62 + } 63 + 64 + // NewPtr wraps an existing pointer. Panics if p is nil. 65 + func NewPtr[T any](p *T) Ptr[T] { 66 + if p == nil { 67 + panic("safety.NewPtr: nil pointer") 68 + } 69 + return Ptr[T]{v: p} 70 + } 71 + 72 + // MakePtr stores the address of a copy of v and is always non-nil. 73 + func MakePtr[T any](v T) Ptr[T] { 74 + return Ptr[T]{v: &v} 75 + } 76 + 77 + // Get returns the underlying non-nil pointer. 78 + func (p Ptr[T]) Get() *T { 79 + return p.v 80 + }
+113
pkg/common/safety/safety_test.go
··· 1 + package safety 2 + 3 + import ( 4 + "testing" 5 + ) 6 + 7 + // ── Optional ───────────────────────────────────────────────────────────────── 8 + 9 + func TestNone(t *testing.T) { 10 + o := None[int]() 11 + if o.Valid { 12 + t.Error("None: expected Valid = false") 13 + } 14 + var zero int 15 + if o.Value != zero { 16 + t.Errorf("None: expected zero value, got %v", o.Value) 17 + } 18 + } 19 + 20 + func TestSome(t *testing.T) { 21 + o := Some(42) 22 + if !o.Valid { 23 + t.Error("Some: expected Valid = true") 24 + } 25 + if o.Value != 42 { 26 + t.Errorf("Some: expected 42, got %v", o.Value) 27 + } 28 + } 29 + 30 + func TestSomePanicsOnNil(t *testing.T) { 31 + defer func() { 32 + if r := recover(); r == nil { 33 + t.Error("Some(nil) should panic") 34 + } 35 + }() 36 + var p *int 37 + _ = Some(p) 38 + } 39 + 40 + func TestSomeDoesNotPanicOnNonNilPointer(t *testing.T) { 41 + v := 42 42 + p := &v 43 + defer func() { 44 + if r := recover(); r != nil { 45 + t.Errorf("Some(non-nil) should not panic, got %v", r) 46 + } 47 + }() 48 + o := Some(p) 49 + if !o.Valid || o.Value != p { 50 + t.Error("expected valid optional wrapping pointer") 51 + } 52 + } 53 + 54 + func TestOptionalGet(t *testing.T) { 55 + present := Some("hello") 56 + v, ok := present.Get() 57 + if !ok || v != "hello" { 58 + t.Errorf("Get present: got (%q, %v), want (\"hello\", true)", v, ok) 59 + } 60 + 61 + absent := None[string]() 62 + v, ok = absent.Get() 63 + if ok || v != "" { 64 + t.Errorf("Get absent: got (%q, %v), want (\"\", false)", v, ok) 65 + } 66 + } 67 + 68 + func TestOptionalOr(t *testing.T) { 69 + present := Some(7) 70 + if got := present.Or(99); got != 7 { 71 + t.Errorf("Or present: got %d, want 7", got) 72 + } 73 + 74 + absent := None[int]() 75 + if got := absent.Or(99); got != 99 { 76 + t.Errorf("Or absent: got %d, want 99", got) 77 + } 78 + } 79 + 80 + // ── Ptr ────────────────────────────────────────────────────────────────────── 81 + 82 + func TestNewPtr(t *testing.T) { 83 + v := 42 84 + p := NewPtr(&v) 85 + if *p.Get() != 42 { 86 + t.Errorf("NewPtr: got %d, want 42", *p.Get()) 87 + } 88 + } 89 + 90 + func TestNewPtrPanicsOnNil(t *testing.T) { 91 + defer func() { 92 + if r := recover(); r == nil { 93 + t.Error("NewPtr(nil) should panic") 94 + } 95 + }() 96 + var p *int 97 + _ = NewPtr(p) 98 + } 99 + 100 + func TestMakePtr(t *testing.T) { 101 + p := MakePtr(42) 102 + if *p.Get() != 42 { 103 + t.Errorf("MakePtr: got %d, want 42", *p.Get()) 104 + } 105 + } 106 + 107 + func TestMakePtrIndependentCopies(t *testing.T) { 108 + p1 := MakePtr(1) 109 + p2 := MakePtr(2) 110 + if *p1.Get() != 1 || *p2.Get() != 2 { 111 + t.Error("MakePtr copies should be independent") 112 + } 113 + }