public static function parse(string $string) : Cookie
    {
        $parts = preg_split('/;\s*/', $string);
        $nameValue = explode('=', array_shift($parts), 2);

        if (count($nameValue) !== 2) {
            throw new \InvalidArgumentException('The cookie string is not valid.');
        }

        [$name, $value] = $nameValue;

        if ($name === '') {
            throw new \InvalidArgumentException('The cookie string is not valid.');
        }

        if ($value === '') {
            throw new \InvalidArgumentException('The cookie string is not valid.');
        }

        $value = rawurldecode($value);
        $expires = 0;
        $path = null;
        $domain = null;
        $secure = false;
        $httpOnly = false;

        foreach ($parts as $part) {
            switch (strtolower($part)) {
                case 'secure':
                    $secure = true;
                    break;

                case 'httponly':
                    $httpOnly = true;
                    break;

                default:
                    $elements = explode('=', $part, 2);
                    if (count($elements) === 2) {
                        switch (strtolower($elements[0])) {
                            case 'expires':
                                // Using @ to suppress the timezone warning, might not be the best thing to do.
                                if (is_int($time = @ strtotime($elements[1]))) {
                                    $expires = $time;
                                }
                                break;

                            case 'path':
                                $path = $elements[1];
                                break;

                            case 'domain':
                                $domain = strtolower(ltrim($elements[1], '.'));
                        }
                    }
            }
        }

        return (new Cookie($name, $value))
            ->setExpires($expires)
            ->setPath($path)
            ->setDomain($domain)
            ->setSecure($secure)
            ->setHttpOnly($httpOnly);
    }