/// <summary> /// Attempts to parse a string as a <see cref="PackageQualityFilter"/>. /// Note that the parse is case insensitive, that white spaces are silently ignored and min/max can be reversed. /// The <paramref name="head"/> is forwarded right after the match: the head may be on any kind of character. /// <para> /// Examples: /// "Stable" (is the same as "Stable-Stable"): only <see cref="PackageQuality.Stable"/> is accepted /// "CI-Stable" (is the same as "-Stable" or "CI-" or ""): everything is accepted. /// "-ReleaseCandidate" (same as "CI-RC" or "CI-ReleaseCandidate"): everything except Stable. /// "Exploratory-Preview": No CI, ReleaseCandidate, nor Stable. /// </para> /// </summary> /// <param name="head">The string to parse (leading and internal white spaces between tokens are skipped).</param> /// <param name="filter">The result.</param> /// <returns>True on success, false on error.</returns> public static bool TryParse(ref ReadOnlySpan <char> head, out PackageQualityFilter filter) { var start = head; head = head.TrimStart(); bool hasMin = PackageQualityExtension.TryMatch(ref head, out var min); bool hasMax = false; PackageQuality max = PackageQuality.Stable; var sHead = head; if ((head = head.TrimStart()).Length > 0 && head[0] == '-') { if (!hasMin) { sHead = head; } head = head.Slice(1).TrimStart(); hasMax = PackageQualityExtension.TryMatch(ref head, out max); if (!hasMax) { head = sHead; } } else { head = sHead; } if (hasMin || hasMax) { if (max == PackageQuality.None) { max = PackageQuality.Stable; } if (min > max) { var t = max; max = min; min = t; } filter = new PackageQualityFilter(min, max == PackageQuality.None ? PackageQuality.Stable : max); return(true); } filter = new PackageQualityFilter(); head = start; return(false); }
/// <summary> /// Tries to parse "<see cref="SVersionLock"/>[,<see cref="PackageQuality"/>]" or "<see cref="PackageQuality"/>[,<see cref="SVersionLock"/>]". /// Note that match is case insensitive, that white spaces are silently ignored, that all "Lock" wan be written as "Locked" and that "rc" is /// a synonym of <see cref="PackageQuality.ReleaseCandidate"/>. /// The <paramref name="head"/> is forwarded right after the match: the head may be on any kind of character. /// </summary> /// <param name="head">The string to parse (leading and internal white spaces are skipped).</param> /// <param name="l">The read lock.</param> /// <param name="q">The read quality.</param> /// <returns>True on success, false otherwise.</returns> public static bool TryParseLockAndMinQuality(ref ReadOnlySpan <char> head, out SVersionLock l, out PackageQuality q) { var sSaved = head; l = SVersionLock.None; q = PackageQuality.None; if (head.Length == 0) { return(false); } if (SVersionLockExtension.TryMatch(ref Trim(ref head), out l)) { if (TryMatch(ref Trim(ref head), ',')) { // This handles None,None: if the first read is "None", then it could have been the "None" of the quality: // if we don't match a Quality we give a second chance to the Lock. if (!PackageQualityExtension.TryMatch(ref Trim(ref head), out q) && l == SVersionLock.None) { SVersionLockExtension.TryMatch(ref Trim(ref head), out l); } return(true); } return(true); } if (PackageQualityExtension.TryMatch(ref Trim(ref head), out q)) { if (TryMatch(ref Trim(ref head), ',')) { SVersionLockExtension.TryMatch(ref Trim(ref head), out l); return(true); } return(true); } head = sSaved; return(false); }