lotus/node/options.go
2019-07-10 15:06:04 +02:00

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()
}