in src/NuGet.Core/NuGet.Versioning/FloatRange.cs [214:361]
public static bool TryParse(string versionString, [NotNullWhen(true)] out FloatRange? range)
{
range = null;
if (versionString != null && !string.IsNullOrWhiteSpace(versionString))
{
var firstStarPosition = IndexOf(versionString, '*');
var lastStarPosition = versionString.LastIndexOf('*');
string? releasePrefix = null;
if (versionString.Length == 1
&& firstStarPosition == 0)
{
range = new FloatRange(NuGetVersionFloatBehavior.Major, new NuGetVersion(new Version(0, 0)));
}
else if (versionString.Equals("*-*", StringComparison.Ordinal))
{
range = new FloatRange(NuGetVersionFloatBehavior.AbsoluteLatest, new NuGetVersion("0.0.0-0"), releasePrefix: string.Empty);
}
else if (firstStarPosition != lastStarPosition && lastStarPosition != -1 && IndexOf(versionString, '+') == -1)
{
var behavior = NuGetVersionFloatBehavior.None;
// 2 *s are only allowed in prerelease versions.
var dashPosition = IndexOf(versionString, '-');
string? actualVersion = null;
if (dashPosition != -1 &&
lastStarPosition == versionString.Length - 1 && // Last star is at the end of the full string
firstStarPosition == (dashPosition - 1) // First star is right before the first dash.
)
{
// Get the stable part.
var stablePart = versionString.Substring(0, dashPosition - 1); // Get the part without the *
stablePart += "0";
var versionParts = CalculateVersionParts(stablePart);
switch (versionParts)
{
case 1:
behavior = NuGetVersionFloatBehavior.PrereleaseMajor;
break;
case 2:
behavior = NuGetVersionFloatBehavior.PrereleaseMinor;
break;
case 3:
behavior = NuGetVersionFloatBehavior.PrereleasePatch;
break;
case 4:
behavior = NuGetVersionFloatBehavior.PrereleaseRevision;
break;
default:
break;
}
var releaseVersion = versionString.Substring(dashPosition + 1);
releasePrefix = releaseVersion.Substring(0, releaseVersion.Length - 1);
var releasePart = releasePrefix;
if (releasePrefix.Length == 0 || releasePrefix.EndsWith(".", StringComparison.Ordinal))
{
// 1.0.0-* scenario, an empty label is not a valid version.
releasePart += "0";
}
actualVersion = stablePart + "-" + releasePart;
}
if (NuGetVersion.TryParse(actualVersion, out NuGetVersion? version))
{
range = new FloatRange(behavior, version, releasePrefix);
}
}
// A single * can only appear as the last char in the string.
// * cannot appear in the metadata section after the +
else if (lastStarPosition == versionString.Length - 1 && IndexOf(versionString, '+') == -1)
{
var behavior = NuGetVersionFloatBehavior.None;
var actualVersion = versionString.Substring(0, versionString.Length - 1);
if (IndexOf(versionString, '-') == -1)
{
// replace the * with a 0
actualVersion += "0";
var versionParts = CalculateVersionParts(actualVersion);
if (versionParts == 2)
{
behavior = NuGetVersionFloatBehavior.Minor;
}
else if (versionParts == 3)
{
behavior = NuGetVersionFloatBehavior.Patch;
}
else if (versionParts == 4)
{
behavior = NuGetVersionFloatBehavior.Revision;
}
}
else
{
behavior = NuGetVersionFloatBehavior.Prerelease;
// check for a prefix
if (IndexOf(versionString, '-') == versionString.LastIndexOf('-'))
{
releasePrefix = actualVersion.Substring(versionString.LastIndexOf('-') + 1);
// For numeric labels 0 is the lowest. For alpha-numeric - is the lowest.
if (releasePrefix.Length == 0 || actualVersion.EndsWith(".", StringComparison.Ordinal))
{
// 1.0.0-* scenario, an empty label is not a valid version.
actualVersion += "0";
}
else if (actualVersion.EndsWith("-", StringComparison.Ordinal))
{
// Append a dash to allow floating on the next character.
actualVersion += "-";
}
}
}
if (NuGetVersion.TryParse(actualVersion, out NuGetVersion? version))
{
range = new FloatRange(behavior, version, releasePrefix);
}
}
else
{
// normal version parse
if (NuGetVersion.TryParse(versionString, out NuGetVersion? version))
{
// there is no float range for this version
range = new FloatRange(NuGetVersionFloatBehavior.None, version);
}
}
}
return range != null;
int IndexOf(string str, char c)
{
#if NETCOREAPP2_0_OR_GREATER
return str.IndexOf(c, StringComparison.Ordinal);
#else
return str.IndexOf(c);
#endif
}
}