package backpack import ( "fmt" "reflect" "sync" ) // Registry is an app-scoped typed service catalog. It has no process-global state. type Registry struct { mu sync.RWMutex m map[reflect.Type]any } // NewRegistry returns an empty service registry. func NewRegistry() *Registry { return &Registry{m: make(map[reflect.Type]any)} } // Publish stores value under the concrete type argument T. Publishing the // same T twice is an error. func (r *Registry) Publish[T any](value T) error { if r == nil { return fmt.Errorf("backpack: registry is nil") } if any(value) == nil { return fmt.Errorf("backpack: publish nil service") } key := reflect.TypeFor[T]() r.mu.Lock() defer r.mu.Unlock() if r.m == nil { r.m = make(map[reflect.Type]any) } if _, exists := r.m[key]; exists { return fmt.Errorf("backpack: duplicate provider for %s", key) } r.m[key] = value return nil } // Lookup returns the service published under T, or (zero, false). func (r *Registry) Lookup[T any]() (T, bool) { var zero T if r == nil { return zero, false } key := reflect.TypeFor[T]() r.mu.RLock() defer r.mu.RUnlock() v, ok := r.m[key] if !ok { return zero, false } got, ok := v.(T) if !ok { return zero, false } return got, true }