public static function parse(string $uri): URI
    {
        if ($uri == '') {
            return new static();
        }

        $parts = parse_url($uri);
        if ($parts === false) {
            throw new \InvalidArgumentException(sprintf('Cannot parse malformed uri "%s".', $uri));
        }

        if (!isset($parts['scheme'])) {
            throw new \InvalidArgumentException(sprintf('Missing scheme in uri "%s".', $uri));
        }

        if (count($parts) == 1 && isset($parts['scheme'])) {
            throw new \InvalidArgumentException(sprintf('Missing hierarchical segment in uri "%s".', $uri));
        }

        $defaults = [
            'scheme' => '',
            'host' => '',
            'user' => '',
            'pass' => '',
            'port' => null,
            'path' => '',
            'query' => '',
            'fragment' => '',
        ];

        $parts = array_merge($defaults, $parts);

        return new static(
            $parts['scheme'],
            $parts['host'],
            $parts['path'],
            $parts['query'],
            $parts['fragment'],
            $parts['user'],
            $parts['pass'],
            $parts['port']
        );
    }