UNPKG

dmclc

Version:

Dolphin Minecraft Launcher Core

189 lines (188 loc) 6.89 kB
/* * Ported from Fabric Loader. * Copyright 2016 FabricMC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import assert from "assert"; import { SemanticVersion } from "./SemanticVersion.js"; import { SemanticVersionImpl } from "./SemanticVersionImpl.js"; import { VersionComparisonOperator } from "./VersionComparisonOperator.js"; import { VersionIntervalImpl } from "./VersionIntervalImpl.js"; import { VersionParser } from "./VersionParser.js"; import { VersionParsingException } from "./VersionParsingException.js"; import { VersionPredicate } from "./VersionPredicate.js"; class VersionPredicateParser { static OPERATORS = VersionComparisonOperator.values; static parseOne(predicate) { const predicateList = []; for (let s of predicate.split(" ")) { s = s.trim(); if (s === "" || s === "*") { continue; } let operator = VersionComparisonOperator.EQUAL; for (const op of VersionPredicateParser.OPERATORS) { if (s.startsWith(op.getSerialized())) { operator = op; s = s.substring(op.getSerialized().length); break; } } let version = VersionParser.parse(s, true); if (version instanceof SemanticVersion) { if (version.hasWildcard()) { // .x version -> replace with conventional version by replacing the operator if (operator != VersionComparisonOperator.EQUAL) { throw new VersionParsingException("Invalid predicate: " + predicate + ", version ranges with wildcards (.X) require using the equality operator or no operator at all!"); } assert(!version.getPrereleaseKey()); const compCount = version.getVersionComponentCount(); assert(compCount == 2 || compCount == 3); operator = compCount == 2 ? VersionComparisonOperator.SAME_TO_NEXT_MAJOR : VersionComparisonOperator.SAME_TO_NEXT_MINOR; const newComponents = new Array(version.getVersionComponentCount() - 1); for (let i = 0; i < version.getVersionComponentCount() - 1; i++) { newComponents[i] = version.getVersionComponent(i); } version = new SemanticVersionImpl(newComponents, "", version.getBuildKey()); } } else if (!operator.isMinInclusive() && !operator.isMaxInclusive()) { // non-semver without inclusive bound throw new VersionParsingException("Invalid predicate: " + predicate + ", version ranges need to be semantic version compatible to use operators that exclude the bound!"); } else { // non-semver with inclusive bound operator = VersionComparisonOperator.EQUAL; } predicateList.push(new SingleVersionPredicate(operator, version)); } if (predicateList.length === 0) { return AnyVersionPredicate.INSTANCE; } else if (predicateList.length == 1) { return predicateList[0]; } else { return new MultiVersionPredicate(predicateList); } } static parse(predicates) { const ret = new Set(); for (const version of predicates) { ret.add(VersionPredicateParser.parseOne(version)); } return ret; } static getAny() { return AnyVersionPredicate.INSTANCE; } } export { VersionPredicateParser }; class AnyVersionPredicate extends VersionPredicate { static INSTANCE = new AnyVersionPredicate(); constructor() { super(); } test() { return true; } getTerms() { return []; } getInterval() { return VersionIntervalImpl.INFINITE; } toString() { return "*"; } } class SingleVersionPredicate { operator; refVersion; constructor(operator, refVersion) { this.operator = operator; this.refVersion = refVersion; } test(version) { return this.operator.test(version, this.refVersion); } getTerms() { return [this]; } getInterval() { if (this.refVersion instanceof SemanticVersion) { return new VersionIntervalImpl(this.operator.minVersion(this.refVersion), this.operator.isMinInclusive(), this.operator.maxVersion(this.refVersion), this.operator.isMaxInclusive()); } else { return new VersionIntervalImpl(this.refVersion, true, this.refVersion, true); } } getOperator() { return this.operator; } getReferenceVersion() { return this.refVersion; } equals(obj) { if (obj instanceof SingleVersionPredicate) { return this.operator == obj.operator && this.refVersion.equals(obj.refVersion); } else { return false; } } toString() { return this.operator.getSerialized().concat(this.refVersion.toString()); } } class MultiVersionPredicate extends VersionPredicate { predicates; constructor(predicates) { super(); this.predicates = predicates; } test(version) { for (const predicate of this.predicates) { if (!predicate.test(version)) return false; } return true; } getTerms() { return this.predicates; } getInterval() { if (this.predicates.length === 0) return AnyVersionPredicate.INSTANCE.getInterval(); let ret = this.predicates[0].getInterval(); for (let i = 1; i < this.predicates.length; i++) { ret = VersionIntervalImpl.andOne(ret, this.predicates[i].getInterval()); } return ret; } equals(obj) { if (obj instanceof MultiVersionPredicate) { return !this.predicates.map((v, i) => obj.predicates[i].equals(v)).includes(false); } else { return false; } } toString() { const ret = []; for (const predicate of this.predicates) { if (ret.length > 0) ret.push(" "); ret.push(predicate.toString()); } return ret.join(""); } }