function connect(connection) {
    // check if the CSV file is already in the storage
    if (getData(connection)) {
        return Promise.resolve(connection);
    }

    const url = connection.database;

    const availableSize = getAvailableSize();
    if (availableSize === -1) {
        throw new Error('Out of memory');
    }

    let getCSVFile;
    if (url.startsWith('data:')) {
        const data = url.slice(1 + url.indexOf(','));

        // base64 encodes 6 bits per byte
        const estimatedSize = data.length * 6 / 8;
        if (availableSize !== 0 && estimatedSize > availableSize) {
            throw new Error('Out of memory');
        }

        const body = new Buffer(url.slice(1 + url.indexOf(',')), 'base64').toString();
        getCSVFile = Promise.resolve(body);

    } else {
        getCSVFile = fetch(url, {size: availableSize}).then(res => res.text());
    }

    return getCSVFile.then(body => {
        const fileSize = body.length;
        if (availableSize !== 0 && fileSize > availableSize) {
            throw new Error('Out of memory');
        }

        return new Promise(function(resolve) {
            papa.parse(body, {
                download: false,
                dynamicTyping: true,
                skipEmptyLines: true,
                header: true,
                worker: true,

                complete: function({data, errors, meta}) {
                    if (errors.length) {
                        throw new Error('Failed to parse CSV file ' + url);
                    }

                    connection.meta = meta;
                    connection.size = fileSize;

                    putData(connection, data);

                    resolve(connection);
                }
            });
        });
    });
}
connect downloads and parses an URL of a CSV file
@param {CSVConnection} connection Connection to a CSV file
@returns {Promise.<CSVConnection>} that resolves when the connection succeeds