mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-28 15:29:09 +01:00
88 lines
2.4 KiB
Go
88 lines
2.4 KiB
Go
package server
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
// Create a dependency and add it to the BaseServer's container. A string key identifier will be based on its type definition.
|
|
func Create[T any](s Server, createFunc func() T) T {
|
|
result, _ := maybeCreate(s, createFunc)
|
|
|
|
return result
|
|
}
|
|
|
|
// CreateNamed is the same as Create but will suffix the dependency string key identifier with a custom name.
|
|
// Useful if you want to have multiple named instances of the same object type.
|
|
func CreateNamed[T any](s Server, name string, createFunc func() T) T {
|
|
result, _ := maybeCreateNamed(s, name, createFunc)
|
|
|
|
return result
|
|
}
|
|
|
|
// Inject lets you override a specific service from outside the BaseServer itself.
|
|
// This is useful for tests
|
|
func Inject[T any](c Server, thing T) {
|
|
_, _ = maybeCreate(c, func() T {
|
|
return thing
|
|
})
|
|
}
|
|
|
|
// InjectNamed is like Inject() but with a custom name.
|
|
func InjectNamed[T any](c Server, name string, thing T) {
|
|
_, _ = maybeCreateKeyed(c, name, func() T {
|
|
return thing
|
|
})
|
|
}
|
|
|
|
func maybeCreate[T any](s Server, createFunc func() T) (result T, isNew bool) {
|
|
return maybeCreateKeyed(s, typeKey(reflect.TypeFor[T]()), createFunc)
|
|
}
|
|
|
|
func maybeCreateNamed[T any](s Server, name string, createFunc func() T) (result T, isNew bool) {
|
|
key := fmt.Sprintf("%s:%s", typeKey(reflect.TypeFor[T]()), name)
|
|
return maybeCreateKeyed(s, key, createFunc)
|
|
}
|
|
|
|
// typeKey names t by the full package path of every named type it is built from, so
|
|
// same-named types of different packages, such as google.golang.org/grpc.Server and a
|
|
// local grpc.Server, never share a container key.
|
|
func typeKey(t reflect.Type) string {
|
|
if t.Name() != "" {
|
|
if t.PkgPath() == "" {
|
|
return t.Name()
|
|
}
|
|
return t.PkgPath() + "." + t.Name()
|
|
}
|
|
|
|
switch t.Kind() {
|
|
case reflect.Pointer:
|
|
return "*" + typeKey(t.Elem())
|
|
case reflect.Slice:
|
|
return "[]" + typeKey(t.Elem())
|
|
case reflect.Array:
|
|
return fmt.Sprintf("[%d]%s", t.Len(), typeKey(t.Elem()))
|
|
case reflect.Map:
|
|
return "map[" + typeKey(t.Key()) + "]" + typeKey(t.Elem())
|
|
case reflect.Chan:
|
|
return t.ChanDir().String() + " " + typeKey(t.Elem())
|
|
default:
|
|
return t.String()
|
|
}
|
|
}
|
|
|
|
func maybeCreateKeyed[T any](s Server, key string, createFunc func() T) (result T, isNew bool) {
|
|
if t, ok := s.GetContainer(key); ok {
|
|
if t == nil {
|
|
return result, false
|
|
}
|
|
return t.(T), false
|
|
}
|
|
|
|
t := createFunc()
|
|
|
|
s.SetContainer(key, t)
|
|
|
|
return t, true
|
|
}
|