93 lines
2.2 KiB
Go
93 lines
2.2 KiB
Go
package node
|
|
|
|
import (
|
|
"reflect"
|
|
)
|
|
|
|
// Option is a functional option which can be used with the New function to
|
|
// change how the node is constructed
|
|
//
|
|
// Options are applied in sequence
|
|
type Option func(*settings) error
|
|
|
|
// Options groups multiple options into one
|
|
func Options(opts ...Option) Option {
|
|
return func(s *settings) error {
|
|
for _, opt := range opts {
|
|
if err := opt(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Error is a special option which returns an error when applied
|
|
func Error(err error) Option {
|
|
return func(_ *settings) error {
|
|
return err
|
|
}
|
|
}
|
|
|
|
func applyIf(check func(s *settings) bool, opts ...Option) Option {
|
|
return func(s *settings) error {
|
|
if check(s) {
|
|
return Options(opts...)(s)
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// from go-ipfs
|
|
// as casts input constructor to a given interface (if a value is given, it
|
|
// wraps it into a constructor).
|
|
//
|
|
// Note: this method may look like a hack, and in fact it is one.
|
|
// This is here only because https://github.com/uber-go/fx/issues/673 wasn't
|
|
// released yet
|
|
//
|
|
// Note 2: when making changes here, make sure this method stays at
|
|
// 100% coverage. This makes it less likely it will be terribly broken
|
|
func as(in interface{}, as interface{}) interface{} {
|
|
outType := reflect.TypeOf(as)
|
|
|
|
if outType.Kind() != reflect.Ptr {
|
|
panic("outType is not a pointer")
|
|
}
|
|
|
|
if reflect.TypeOf(in).Kind() != reflect.Func {
|
|
ctype := reflect.FuncOf(nil, []reflect.Type{outType.Elem()}, false)
|
|
|
|
return reflect.MakeFunc(ctype, func(args []reflect.Value) (results []reflect.Value) {
|
|
out := reflect.New(outType.Elem())
|
|
out.Elem().Set(reflect.ValueOf(in))
|
|
|
|
return []reflect.Value{out.Elem()}
|
|
}).Interface()
|
|
}
|
|
|
|
inType := reflect.TypeOf(in)
|
|
|
|
ins := make([]reflect.Type, inType.NumIn())
|
|
outs := make([]reflect.Type, inType.NumOut())
|
|
|
|
for i := range ins {
|
|
ins[i] = inType.In(i)
|
|
}
|
|
outs[0] = outType.Elem()
|
|
for i := range outs[1:] {
|
|
outs[i+1] = inType.Out(i + 1)
|
|
}
|
|
|
|
ctype := reflect.FuncOf(ins, outs, false)
|
|
|
|
return reflect.MakeFunc(ctype, func(args []reflect.Value) (results []reflect.Value) {
|
|
outs := reflect.ValueOf(in).Call(args)
|
|
out := reflect.New(outType.Elem())
|
|
out.Elem().Set(outs[0])
|
|
outs[0] = out.Elem()
|
|
|
|
return outs
|
|
}).Interface()
|
|
}
|