"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.api = exports.isValid = exports.supportedRangeStrategies = exports.supportsRanges = exports.urls = exports.displayName = exports.id = void 0;
const logger_1 = require("../../../logger");
const regex_1 = require("../../../util/regex");
const npm_1 = require("../npm");
exports.id = 'cargo';
exports.displayName = 'Cargo';
exports.urls = [
    'https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html',
];
exports.supportsRanges = true;
exports.supportedRangeStrategies = [
    'bump',
    'pin',
    'replace',
];
const isVersion = (input) => npm_1.api.isVersion(input);
function convertToCaret(item) {
    // In Cargo, caret versions are used by default, so "1.2.3" actually means ^1.2.3.
    // Similarly, "0.4" actually means ^0.4.
    // See: https://doc.rust-lang.org/stable/cargo/reference/specifying-dependencies.html#caret-requirements
    if (isVersion(item) || isVersion(item + '.0') || isVersion(item + '.0.0')) {
        return '^' + item.trim();
    }
    return item.trim();
}
function cargo2npm(input) {
    let versions = input.split(',');
    versions = versions.map(convertToCaret);
    return versions.join(' ');
}
function notEmpty(s) {
    return s !== '';
}
function npm2cargo(input) {
    // istanbul ignore if
    if (!input) {
        return input;
    }
    // Note: this doesn't remove the ^
    const res = input
        .split((0, regex_1.regEx)(/\s+,?\s*|\s*,?\s+/))
        .map((str) => str.trim())
        .filter(notEmpty);
    const operators = ['^', '~', '=', '>', '<', '<=', '>='];
    for (let i = 0; i < res.length - 1; i += 1) {
        if (operators.includes(res[i])) {
            const newValue = res[i] + ' ' + res[i + 1];
            res.splice(i, 2, newValue);
        }
    }
    return res.join(', ');
}
const isLessThanRange = (version, range) => !!npm_1.api.isLessThanRange?.(version, cargo2npm(range));
const isValid = (input) => npm_1.api.isValid(cargo2npm(input));
exports.isValid = isValid;
const matches = (version, range) => npm_1.api.matches(version, cargo2npm(range));
function getSatisfyingVersion(versions, range) {
    return npm_1.api.getSatisfyingVersion(versions, cargo2npm(range));
}
function minSatisfyingVersion(versions, range) {
    return npm_1.api.minSatisfyingVersion(versions, cargo2npm(range));
}
const isSingleVersion = (constraint) => constraint.trim().startsWith('=') &&
    isVersion(constraint.trim().substring(1).trim());
function getNewValue({ currentValue, rangeStrategy, currentVersion, newVersion, }) {
    if (!currentValue || currentValue === '*') {
        return rangeStrategy === 'pin' ? `=${newVersion}` : currentValue;
    }
    if (rangeStrategy === 'pin' || isSingleVersion(currentValue)) {
        let res = '=';
        if (currentValue.startsWith('= ')) {
            res += ' ';
        }
        res += newVersion;
        return res;
    }
    const newSemver = npm_1.api.getNewValue({
        currentValue: cargo2npm(currentValue),
        rangeStrategy,
        currentVersion,
        newVersion,
    });
    let newCargo = newSemver
        ? npm2cargo(newSemver)
        : /* istanbul ignore next: should never happen */ null;
    // istanbul ignore if
    if (!newCargo) {
        logger_1.logger.info({ currentValue, newSemver }, 'Could not get cargo version from semver');
        return currentValue;
    }
    // Keep new range precision the same as current
    if ((currentValue.startsWith('~') || currentValue.startsWith('^')) &&
        rangeStrategy === 'replace' &&
        newCargo.split('.').length > currentValue.split('.').length) {
        newCargo = newCargo
            .split('.')
            .slice(0, currentValue.split('.').length)
            .join('.');
    }
    // Try to reverse any caret we added
    if (newCargo.startsWith('^') && !currentValue.startsWith('^')) {
        const withoutCaret = newCargo.substring(1);
        // NOTE: We want the number of components in the new version to match the original.
        // e.g. "5.0" should be updated to "6.0".
        const components = currentValue.split('.').length;
        newCargo = withoutCaret.split('.').slice(0, components).join('.');
    }
    return newCargo;
}
exports.api = {
    ...npm_1.api,
    getNewValue,
    isLessThanRange,
    isSingleVersion,
    isValid: exports.isValid,
    matches,
    getSatisfyingVersion,
    minSatisfyingVersion,
};
exports.default = exports.api;
//# sourceMappingURL=index.js.map