1package sentinel
2
3import (
4 "github.com/openai/openai-go/internal/encoding/json/shims"
5 "reflect"
6 "sync"
7)
8
9type cacheEntry struct {
10 x any
11 ptr uintptr
12 kind reflect.Kind
13}
14
15var nullCache sync.Map // map[reflect.Type]cacheEntry
16
17func NewNullSentinel[T any](mk func() T) T {
18 t := shims.TypeFor[T]()
19 entry, loaded := nullCache.Load(t) // avoid premature allocation
20 if !loaded {
21 x := mk()
22 ptr := reflect.ValueOf(x).Pointer()
23 entry, _ = nullCache.LoadOrStore(t, cacheEntry{x, ptr, t.Kind()})
24 }
25 return entry.(cacheEntry).x.(T)
26}
27
28// for internal use only
29func IsValueNull(v reflect.Value) bool {
30 switch v.Kind() {
31 case reflect.Map, reflect.Slice:
32 null, ok := nullCache.Load(v.Type())
33 return ok && v.Pointer() == null.(cacheEntry).ptr
34 }
35 return false
36}
37
38func IsNull[T any](v T) bool {
39 t := shims.TypeFor[T]()
40 switch t.Kind() {
41 case reflect.Map, reflect.Slice:
42 null, ok := nullCache.Load(t)
43 return ok && reflect.ValueOf(v).Pointer() == null.(cacheEntry).ptr
44 }
45 return false
46}