import { __read, __spread, __values } from "tslib";
import Path from 'path';
import fs from 'fs-extra';
var DiskCache = /** @class */ (function () {
    function DiskCache(basePath) {
        this.basePath = basePath;
        /**
         * Array of substring lengths, used to split the key into shorter strings.
         * Useful for filesystem caching, since fs performance is better when using
         * a nested tree of directories rather than a single directory containing
         * all cache entries. (See also: how git splits up the contents of `.git/objects`)
         *
         * For the default: [40, 2], the cache path will be a directory with the first 40 characters,
         * a directory with the next 2, and then the filename with the remainder.
         */
        this.splitLengths = [40, 2];
    }
    DiskCache.prototype.splitKey = function (key) {
        var e_1, _a;
        var split = [];
        var start = 0;
        try {
            for (var _b = __values(this.splitLengths), _c = _b.next(); !_c.done; _c = _b.next()) {
                var splitPoint = _c.value;
                split.push(key.slice(start, start + splitPoint));
                start = splitPoint;
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
            }
            finally { if (e_1) throw e_1.error; }
        }
        split.push(key.slice(start));
        return split;
    };
    DiskCache.prototype.keyToAbsPath = function (key) {
        return Path.join.apply(Path, __spread([this.basePath], this.splitKey(key)));
    };
    DiskCache.prototype.get = function (key) {
        var p = this.keyToAbsPath(key);
        return readSafe(p);
    };
    DiskCache.prototype.set = function (key, value) {
        var _value = toBuffer(value);
        var path = this.keyToAbsPath(key);
        writeSafe(path, _value);
    };
    return DiskCache;
}());
export { DiskCache };
/**
 * Every cache entry has these bytes at the end.
 * Thus if we read a cache entry and it doesn't end this way, we know
 * another process is mid-write and we can't safely read the entry.
 */
var ENDING = Buffer.from([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
function readSafe(path) {
    try {
        var buffer = fs.readFileSync(path);
        var ending = buffer.slice(-ENDING.length);
        if (ending.compare(ENDING) !== 0)
            return null;
        return buffer.slice(0, -ENDING.length);
    }
    catch (e) {
        if (e.code === 'ENOENT')
            return null;
        throw e;
    }
}
function writeSafe(path, buffer) {
    fs.mkdirpSync(Path.dirname(path));
    var fd = fs.openSync(path, 'w');
    fs.writeSync(fd, buffer);
    fs.writeSync(fd, ENDING);
    fs.closeSync(fd);
}
function toBuffer(b) {
    if (typeof b === 'string')
        return Buffer.from(b, 'utf8');
    return b;
}
//# sourceMappingURL=cache.mjs.map