/* * darwin-apk © 2024 Gay Pizza Specifications * SPDX-License-Identifier: Apache-2.0 */ import Foundation internal struct ApkVersionRequirement: Sendable, Hashable { let name: String let versionSpec: ApkVersionSpecification init(name: String, spec: ApkVersionSpecification) { self.name = name self.versionSpec = spec } init(extract: Substring) throws(ParseError) { var comparer: ComparatorBits = [] var dependStr = extract[...] let nameEnd: String.Index, versionStart: String.Index // Check for bang prefix to indicate a conflict if dependStr.first == "!" { comparer.insert(.conflict) dependStr = dependStr[dependStr.index(after: dependStr.startIndex)...] } // Match comparator if let range = dependStr.firstRange(where: { [ "<", "=", ">", "~" ].contains($0) }) { for c in dependStr[range] { switch c { case "<": comparer.insert(.less) case "=": comparer.insert(.equals) case ">": comparer.insert(.greater) case "~": comparer.formUnion([ .fuzzy, .equals ]) default: break } } (nameEnd, versionStart) = (range.lowerBound, range.upperBound) } else { comparer.formUnion(.any) (nameEnd, versionStart) = (dependStr.endIndex, dependStr.endIndex) } // Parse version specification self.versionSpec = try ApkVersionSpecification(comparer, version: dependStr[versionStart...]) self.name = String(dependStr[.. Bool) rethrows -> Range? { guard let start = try self.firstIndex(where: predicate) else { return nil } var idx = start repeat { idx = self.index(after: idx) } while try idx != self.endIndex && predicate(self[idx]) return start..