in unpack.go [119:159]
func implementsUnpacker(t reflect.Type) bool {
// ucfg.Config or structures that can be casted to ucfg.Config are not
// Unpackers.
if tConfig.ConvertibleTo(chaseTypePointers(t)) {
return false
}
for _, tUnpack := range tUnpackers {
if t.Implements(tUnpack) {
return true
}
}
if t.NumMethod() == 0 {
return false
}
// test if object has 'Unpack' method
method, ok := t.MethodByName("Unpack")
if !ok {
return false
}
// check method input and output parameters to match the ConfigUnpacker interface:
// func (to *T) Unpack(cfg *TConfig) error
// with T being the method receiver (input paramter 0)
// and TConfig being the aliased config type to convert to (input parameter 1)
paramCountCheck := method.Type.NumIn() == 2 && method.Type.NumOut() == 1
if !paramCountCheck {
return false
}
if !method.Type.Out(0).Implements(tError) {
// return variable is not compatible to `error` type
return false
}
// method receiver is known, check config parameters being compatible
tIn := method.Type.In(1)
return tConfig.ConvertibleTo(tIn) || tConfigPtr.ConvertibleTo(tIn)
}