Skip to content

Commit

Permalink
add IsOSPlatformOrLater and IsOSPlatformEarlierThan methods (#39005)
Browse files Browse the repository at this point in the history
* add tests for IsOSPlatformOrLater and IsOSPlatformEarlierThan methods

* add IsOSPlatformOrLater and IsOSPlatformEarlierThan methods

* add xml docs that explain what the API does and what input is supported

* address code review feedback

* numbers in the middle of the platform name are not supported
  • Loading branch information
adamsitnik committed Jul 10, 2020
1 parent 385efa8 commit 3480a74
Show file tree
Hide file tree
Showing 6 changed files with 390 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,15 @@ public static partial class RuntimeInformation
public static System.Runtime.InteropServices.Architecture ProcessArchitecture { get { throw null; } }
public static string RuntimeIdentifier { get { throw null; } }
public static bool IsOSPlatform(System.Runtime.InteropServices.OSPlatform osPlatform) { throw null; }
public static bool IsOSPlatformOrLater(string platformName) { throw null; }
public static bool IsOSPlatformOrLater(System.Runtime.InteropServices.OSPlatform osPlatform, int major) { throw null; }
public static bool IsOSPlatformOrLater(System.Runtime.InteropServices.OSPlatform osPlatform, int major, int minor) { throw null; }
public static bool IsOSPlatformOrLater(System.Runtime.InteropServices.OSPlatform osPlatform, int major, int minor, int build) { throw null; }
public static bool IsOSPlatformOrLater(System.Runtime.InteropServices.OSPlatform osPlatform, int major, int minor, int build, int revision) { throw null; }
public static bool IsOSPlatformEarlierThan(string platformName) { throw null; }
public static bool IsOSPlatformEarlierThan(System.Runtime.InteropServices.OSPlatform osPlatform, int major) { throw null; }
public static bool IsOSPlatformEarlierThan(System.Runtime.InteropServices.OSPlatform osPlatform, int major, int minor) { throw null; }
public static bool IsOSPlatformEarlierThan(System.Runtime.InteropServices.OSPlatform osPlatform, int major, int minor, int build) { throw null; }
public static bool IsOSPlatformEarlierThan(System.Runtime.InteropServices.OSPlatform osPlatform, int major, int minor, int build, int revision) { throw null; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@
<data name="Argument_EmptyValue" xml:space="preserve">
<value>Value cannot be empty.</value>
</data>
<data name="Argument_InvalidPlatfromName" xml:space="preserve">
<value>"{0}" is not a valid platform name. It must contain both name and version (with at least major and minor number specified). Example: "ios14.0".</value>
</data>
<data name="PlatformNotSupported_RuntimeInformation" xml:space="preserve">
<value>RuntimeInformation is not supported for Portable Class Libraries.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="System\Runtime\InteropServices\RuntimeInformation\RuntimeInformation.cs" />
<Compile Include="System\Runtime\InteropServices\RuntimeInformation\RuntimeInformation.PlatformVersion.cs" />
<Compile Include="System\Runtime\InteropServices\RuntimeInformation\Architecture.cs" />
<Compile Include="System\Runtime\InteropServices\RuntimeInformation\OSPlatform.cs" />
</ItemGroup>
Expand Down Expand Up @@ -45,5 +46,6 @@
<Reference Include="System.Runtime" />
<Reference Include="System.Runtime.InteropServices" />
<Reference Include="System.Threading" />
<Reference Include="System.Memory" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Runtime.InteropServices
{
public static partial class RuntimeInformation
{
/// <summary>
/// Check for the OS with a >= version comparison. Used to guard APIs that were added in the given OS release.
/// </summary>
/// <param name="platformName">OS name concatenated with a version number.</param>
/// <remarks>The version number must contain at least major and minor numbers separated with a dot.
/// Example: "ios14.0" is OK, "ios14" is NOT OK.</remarks>
public static bool IsOSPlatformOrLater(string platformName)
{
(OSPlatform platform, Version version) = Parse(platformName);

return IsOSPlatformOrLater(platform, version.Major, version.Minor, version.Build, version.Revision);
}

/// <summary>
/// Check for the OS with a >= version comparison. Used to guard APIs that were added in the given OS release.
/// </summary>
public static bool IsOSPlatformOrLater(OSPlatform osPlatform, int major)
=> IsOSPlatform(osPlatform) && Environment.OSVersion.Version.Major >= major;

/// <summary>
/// Check for the OS with a >= version comparison. Used to guard APIs that were added in the given OS release.
/// </summary>
public static bool IsOSPlatformOrLater(OSPlatform osPlatform, int major, int minor)
=> IsOSPlatform(osPlatform) && IsOSVersionOrLater(major, minor, int.MinValue, int.MinValue);

/// <summary>
/// Check for the OS with a >= version comparison. Used to guard APIs that were added in the given OS release.
/// </summary>
public static bool IsOSPlatformOrLater(OSPlatform osPlatform, int major, int minor, int build)
=> IsOSPlatform(osPlatform) && IsOSVersionOrLater(major, minor, build, int.MinValue);

/// <summary>
/// Check for the OS with a >= version comparison. Used to guard APIs that were added in the given OS release.
/// </summary>
public static bool IsOSPlatformOrLater(OSPlatform osPlatform, int major, int minor, int build, int revision)
=> IsOSPlatform(osPlatform) && IsOSVersionOrLater(major, minor, build, revision);

/// <summary>
/// Check for the OS with a &lt; version comparison. Used to guard APIs that were obsoleted or removed in the given OS release.
/// </summary>
/// <param name="platformName">OS name concatenated with a version number.</param>
/// <remarks>The version number must contain at least major and minor numbers separated with a dot.
/// Example: "ios14.0" is OK, "ios14" is NOT OK.</remarks>
public static bool IsOSPlatformEarlierThan(string platformName)
{
(OSPlatform platform, Version version) = Parse(platformName);

return IsOSPlatformEarlierThan(platform, version.Major, version.Minor, version.Build, version.Revision);
}

/// <summary>
/// Check for the OS with a &lt; version comparison. Used to guard APIs that were obsoleted or removed in the given OS release.
/// </summary>
public static bool IsOSPlatformEarlierThan(OSPlatform osPlatform, int major)
=> IsOSPlatform(osPlatform) && Environment.OSVersion.Version.Major < major;

/// <summary>
/// Check for the OS with a &lt; version comparison. Used to guard APIs that were obsoleted or removed in the given OS release.
/// </summary>
public static bool IsOSPlatformEarlierThan(OSPlatform osPlatform, int major, int minor)
=> IsOSPlatform(osPlatform) && !IsOSVersionOrLater(major, minor, int.MinValue, int.MinValue);

/// <summary>
/// Check for the OS with a &lt; version comparison. Used to guard APIs that were obsoleted or removed in the given OS release.
/// </summary>
public static bool IsOSPlatformEarlierThan(OSPlatform osPlatform, int major, int minor, int build)
=> IsOSPlatform(osPlatform) && !IsOSVersionOrLater(major, minor, build, int.MinValue);

/// <summary>
/// Check for the OS with a &lt; version comparison. Used to guard APIs that were obsoleted or removed in the given OS release.
/// </summary>
public static bool IsOSPlatformEarlierThan(OSPlatform osPlatform, int major, int minor, int build, int revision)
=> IsOSPlatform(osPlatform) && !IsOSVersionOrLater(major, minor, build, revision);

private static bool IsOSVersionOrLater(int major, int minor, int build, int revision)
{
Version current = Environment.OSVersion.Version;
if (current.Major != major)
{
return current.Major > major;
}
if (current.Minor != minor)
{
return current.Minor > minor;
}
if (current.Build != build)
{
return current.Build > build;
}

return current.Revision >= revision;
}

private static (OSPlatform, Version) Parse(string platformName)
{
if (platformName == null)
{
throw new ArgumentNullException(nameof(platformName));
}
if (platformName.Length == 0)
{
throw new ArgumentException(SR.Argument_EmptyValue, nameof(platformName));
}

// iterate from the begining, as digits in the middle of the names are not supported by design
for (int i = 0; i < platformName.Length; i++)
{
if (char.IsDigit(platformName[i]))
{
if (i > 0 && Version.TryParse(platformName.AsSpan(i), out Version? version))
{
return (OSPlatform.Create(platformName.Substring(0, i)), version);
}
else
{
break;
}
}
}

throw new ArgumentException(SR.Format(SR.Argument_InvalidPlatfromName, platformName), nameof(platformName));
}
}
}
Loading

0 comments on commit 3480a74

Please sign in to comment.