private function parse(string $dsn): void
    {
        $dsnParts = explode(';', $dsn);
        $location = $dsnParts[0];
        unset($dsnParts[0]);
        $locationParts = parse_url($location);

        if ($locationParts === false ||
            (array_key_exists('scheme', $locationParts) && \strlen($locationParts['scheme']) === 1)
        ) {
            preg_match(static::WINDOWS_DSN, $dsn, $locationParts);
        }

        if (! array_key_exists('scheme', $locationParts) ||
            ($locationParts['scheme'] === '' && array_key_exists('path', $locationParts))
        ) {
            $locationParts['scheme'] = 'file';
            $location = 'file://' . $location;
        }

        if (!filter_var($location, FILTER_VALIDATE_URL) && !preg_match(static::WINDOWS_DSN, $location)) {
            throw new InvalidArgumentException(
                sprintf('"%s" is not a valid DSN.', $dsn)
            );
        }

        $this->parseDsn($location, $dsnParts);

        $this->parseScheme($locationParts);

        $this->parseHostAndPath($locationParts);

        $this->parsePort($locationParts);

        $this->user = $locationParts['user'] ?? '';

        $this->password = $locationParts['pass'] ?? '';

        $this->parseQuery($locationParts);

        $this->parseParameters($dsnParts);
    }