Load arguments for callable.

@param array|\stdClass $data
@param callable        $callable
@param Context         $context

@return array Unserialized arguments as positional array.
358159
public function loadArguments($data, callable $callable, Context $context): array
    {
        if (is_object($data) && $data instanceof \stdClass) {
            $data = get_object_vars($data);
        }

        if (!is_array($data)) {
            throw new InvalidDataException('Argument data must array or stdClass');
        }

        $metadata = $this->callableMetadataProvider->getCallableMetadata($callable);

        $args = [];
        $paramPos = 0;
        $argPos = 0;
        while ($paramPos < count($metadata->parameters)) {
            $param = $metadata->parameters[$paramPos];
            $mangledName = $this->nameMangler->mangle($param->name);

            $key = null;
            if (array_key_exists($argPos, $data)) {
                $key = $argPos;
            } elseif (array_key_exists($mangledName, $data)) {
                $key = $mangledName;
            }

            if ($key !== null) {
                $context->pushPath('$' . $key);
                try {
                    $args[] = $this->loader->load($data[$key], $param->type, $context);
                } finally {
                    unset($data[$key]);
                    $context->popPath();
                }
            } elseif ($param->optional) {
                if ($param->variadic) {
                    break;
                }
                $args[] = $param->defaultValue;
            } else {
                throw new InvalidDataException("Required argument $param->name missing");
            }

            $argPos++;
            if (!$param->variadic) {
                $paramPos++;
            }
        }

        if (!empty($data) && $this->throwOnUnknownArgument) {
            throw new InvalidDataException(
                'Some arguments could not be matched: ' . implode(', ', array_keys($data))
            );
        }

        return $args;
    }
145653
public function loadObject($data)
    {
        if (!\is_object($data)) {
            throw new \InvalidArgumentException('param type error! must is object.');
        }

        return $this->bindData($this->data, $data);
    }
919333
public static function call(callable $callable, $args=[])
    {
        if (!is_array($args)) {
            $args = [$args];
        }

        switch (count($args)) {
            case 0:
                return call_user_func($callable);
            case 1:
                return call_user_func($callable, $args[0]);
            case 2:
                return call_user_func($callable, $args[0], $args[1]);
            case 3:
                return call_user_func($callable, $args[0], $args[1], $args[2]);
            case 4:
                return call_user_func($callable, $args[0], $args[1], $args[2], $args[3]);
        }

        return call_user_func_array($callable, $args);
    }
701459
public static function call($callable, $args)
    {
        if (is_scalar($callable) && mb_orig_strpos($callable, '::') === false) {
            return self::callFunction('', $callable, $args);
        }

        if (is_scalar($callable)) {
            $parts = explode('::', $callable);
            if (count($parts) != 2) {
                throw new \RuntimeException("Invalid callable format for '$callable', expected single '::'");
            }
            list($obj, $method) = $parts;
        } else if (is_array($callable)) {
            if (count($callable) != 2) {
                throw new \RuntimeException("Invalid callable format, expected array of exactly 2 elements");
            }
            list($obj, $method) = $callable;
        } else {
            return call_user_func_array($callable, $args);
        }

        if (is_object($obj)) {
            return self::callMethod($obj, null, $method, $args, true);
        } else if (is_scalar($obj)) {
            return self::callStaticMethod($obj, $method, $args, true);
        }

        throw new \RuntimeException("Invalid callable format, expected first array element to be object or scalar, " . gettype($obj) . " given");
    }
1120854
static function makeReflectFromCallable(callable $callable)
    {
        if ( $callable instanceof ipInvokableCallback )
            $callable = $callable->getCallable();

        if ( is_array($callable) )
            // [className_orObject, 'method_name']
            $reflection = new \ReflectionMethod($callable[0], $callable[1]);

        if ( is_string($callable) ) {
            if ( strpos($callable, '::') )
                // 'classname::method'
                $reflection = new \ReflectionMethod($callable);
            else
                // 'function_name'
                $reflection = new \ReflectionFunction($callable);
        }

        if ( method_exists($callable, '__invoke') ) {
            // Closure and Invokable
            if ($callable instanceof \Closure)
                $reflection = new \ReflectionFunction($callable);
            else
                $reflection = new \ReflectionMethod($callable, '__invoke');
        }

        if (! isset($reflection) )
            throw new \ReflectionException;

        return $reflection;
    }
661089
protected function callFast(callable $callable, array $params = [])
    {

        // call_user_func_array seems to be slow
        switch (count($params)) {
            case 1:
                return call_user_func($callable, $params[0]);
            case 2:
                return call_user_func($callable, $params[0], $params[1]);
            case 3:
                return call_user_func($callable, $params[0], $params[1], $params[2]);
            case 4:
                return call_user_func($callable, $params[0], $params[1], $params[2], $params[3]);
            default:
                return call_user_func_array($callable, $params);
        }
    }
927745
protected function executeCallable($callable, array $arguments = [])
    {
        // resolve a pseudo callable to real callable
        $call = $this->resolvePseudoCallable($callable);

        // execute the callable
        return call_user_func_array(
            $call,
            $this->resolveCallableArguments($call, $arguments)
        );
    }
685889
public function setCallable($callable)
    {
        $matches = array();
        if (is_string($callable) && preg_match('!^([^\:]+)\:([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)$!', $callable, $matches)) {
            $class = $matches[1];
            $method = $matches[2];
            $callable = function() use ($class, $method) {
                static $obj = null;
                if ($obj === null) {
                    $obj = new $class;
                }
                return call_user_func_array(array($obj, $method), func_get_args());
            };
        }

        if (!is_callable($callable)) {
            throw new \InvalidArgumentException('Route callable must be callable');
        }

        $this->callable = $callable;
    }
1173851
public static function decode($data, array $context = [])
    {
        $context = array_merge(static::$defaultDecodeContext, $context);

        return static::decodeData($data, $context);
    }
760537
public function render(array $data, ContextInterface $context)
    {
        $data += ['class' => ''];
        $data['class'] .= ' filled-in ';
        $data['class'] = trim($data['class']);

        return parent::render($data, $context);
    }
975105
private function getParametersInOrder(callable $callable): array
    {
        if (null === $this->parametersCache) {
            $this->parametersCache = $this->listParameters($callable);
        }

        return $this->parametersCache;
    }
284138
protected function callControllerCallable(callable $callable, array $parameters = [])
    {
        try {
            return $this->prepareResponse(
                $this->call($callable, $parameters)
            );
        } catch (HttpResponseException $e) {
            return $e->getResponse();
        }
    }
954032
protected static function decode($data, array $context)
    {
        if ($context['base64_decode_url_safe']) {
            $data = static::getUrlSafeData($data);
        }

        $result = base64_decode($data, $context['base64_decode_strict']);

        if (false === $result) {
            static::throwDecodingException($data);
        }

        return $result;
    }
127074
public static function invokeCallable($callable, $args = null)
    {
        if (null != $args) {
            if (is_array($args)) {
                $results = call_user_func_array($callable, $args);
            } else {
                $results = call_user_func($callable, $args);
            }
        } else {
            $results = call_user_func($callable);
        }

        return $results;
    }
879876
public function getByCallable($callable)
    {
        if(!is_array($callable))
        {
            return null;
        }
        list($object, $methodName) = $callable;
        if($object instanceof IBean)
        {
            $className = get_parent_class($object);
        }
        else
        {
            $className = get_class($object);
        }
        $shortClassName = Imi::getClassShortName($className);
        
        $isClassView = false;
        $view = AnnotationManager::getMethodAnnotations($className, $methodName, View::class)[0] ?? null;
        if(null === $view)
        {
            $view = AnnotationManager::getClassAnnotations($className, View::class)[0] ?? null;
            if(null === $view)
            {
                $view = new View([
                    'template' => File::path($shortClassName, $methodName),
                ]);
            }
            else
            {
                $isClassView = true;
            }
        }

        // baseDir
        if(null === $view->baseDir && !$isClassView)
        {
            $classView = AnnotationManager::getClassAnnotations($className, View::class)[0] ?? null;
            if($classView)
            {
                $view->baseDir = $classView->baseDir;
            }
        }
        return $view;
    }
562038
protected function resolveCallableArguments(
        callable $callable,
        array $providedArguments
    )/*# : array */ {
        // object with __invoke defined or \Closure
        if (is_object($callable) && !$callable instanceof \Closure) {
            $reflector = new \ReflectionClass($callable);
            $method = $reflector->getMethod('__invoke');

        // array-like callable
        } elseif (is_array($callable)) {
            $reflector = new \ReflectionClass($callable[0]);
            $method = $reflector->getMethod($callable[1]);

        // simple function
        } else {
            $method = new \ReflectionFunction($callable);
        }

        // dereference the provided arguments
        $this->dereferenceArray($providedArguments);

        // match provided arguments with method parameter definitions
        return $this->matchMethodArguments(
            $method->getParameters(),
            $providedArguments
        );
    }
827158
public function invoke(Callable $callable, array $args = [])
    {
        // object/class method
        if (is_string($callable) && false !== strpos($callable, '::')) {
            $callable = explode('::', $callable);
        }
        if (is_array($callable)) {
            $reflection = new \ReflectionMethod($callable[0], $callable[1]);
        }

        // closures, functions and any other callable
        if (!isset($reflection)) {
            $reflection = new \ReflectionFunction($callable);
        }

        // inject arguments
        $arguments = $this->inject($reflection, $args);
        return $callable(...$arguments);
    }