From 417002efda62b1315f4398ab6c71e6f752d223a2 Mon Sep 17 00:00:00 2001 From: Jared Marsau Date: Mon, 31 Jul 2023 11:38:40 -0700 Subject: [PATCH] Availability Attribute additions and clean-up. (#6) * Added one more availability attribute - the Unavailable attribute for indicating runtime operating systems that might not support a particular API. * Updated version parsing code to use a regular expressions; some Unity builds were not deducing overloads of String.Split correctly. * Small fixes to prevent bad input and addressing of typos. --- .../Runtime/AvailabilityAttributes.cs | 40 ++++++++++++---- .../Apple.Core/Runtime/RuntimeEnvironment.cs | 46 +++++++++---------- 2 files changed, 54 insertions(+), 32 deletions(-) diff --git a/plug-ins/Apple.Core/Apple.Core_Unity/Assets/Apple.Core/Runtime/AvailabilityAttributes.cs b/plug-ins/Apple.Core/Apple.Core_Unity/Assets/Apple.Core/Runtime/AvailabilityAttributes.cs index c6499b11..345346fc 100644 --- a/plug-ins/Apple.Core/Apple.Core_Unity/Assets/Apple.Core/Runtime/AvailabilityAttributes.cs +++ b/plug-ins/Apple.Core/Apple.Core_Unity/Assets/Apple.Core/Runtime/AvailabilityAttributes.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Apple.Core { @@ -11,25 +12,46 @@ namespace Apple.Core public class IntroducedAttribute : Attribute { // Access by property - public RuntimeVersion? iOS { get => _osVersionNumbers[(int)RuntimeOperatingSystem.iOS]; } - public RuntimeVersion? macOS { get => _osVersionNumbers[(int)RuntimeOperatingSystem.macOS]; } - public RuntimeVersion? tvOS { get => _osVersionNumbers[(int)RuntimeOperatingSystem.tvOS]; } + public RuntimeVersion? iOS { get => _osVersions[RuntimeOperatingSystem.iOS]; } + public RuntimeVersion? macOS { get => _osVersions[RuntimeOperatingSystem.macOS]; } + public RuntimeVersion? tvOS { get => _osVersions[RuntimeOperatingSystem.tvOS]; } // Access by OperatingSystem public RuntimeVersion? OperatingSystemVersion(RuntimeOperatingSystem operatingSystem) { - return _osVersionNumbers[(int)operatingSystem]; + if (!Enum.IsDefined(typeof(RuntimeOperatingSystem), operatingSystem) || (operatingSystem == RuntimeOperatingSystem.Unknown) || (operatingSystem == RuntimeOperatingSystem.RuntimeOperatingSystemCount)) + { + return null; + } + + return _osVersions[operatingSystem]; } - protected RuntimeVersion?[] _osVersionNumbers; + protected SortedList _osVersions; public IntroducedAttribute(string iOS = "", string macOS = "", string tvOS = "") { - _osVersionNumbers = new RuntimeVersion?[(int)RuntimeOperatingSystem.RuntimeOperatingSystemCount]; + _osVersions = new SortedList(); - _osVersionNumbers[(int)RuntimeOperatingSystem.iOS] = RuntimeVersion.FromString(iOS); - _osVersionNumbers[(int)RuntimeOperatingSystem.macOS] = RuntimeVersion.FromString(macOS); - _osVersionNumbers[(int)RuntimeOperatingSystem.tvOS] = RuntimeVersion.FromString(tvOS); + _osVersions[RuntimeOperatingSystem.iOS] = RuntimeVersion.FromString(iOS); + _osVersions[RuntimeOperatingSystem.macOS] = RuntimeVersion.FromString(macOS); + _osVersions[RuntimeOperatingSystem.tvOS] = RuntimeVersion.FromString(tvOS); + } + } + + /// + /// UnavailableAttribute is used to indicate operating systems for which an API is *not* available. + /// Example: [Apple.Core.Unavailable(RuntimeOperatingSystem.tvOS)] means that a given API is not available for tvOS, but is available for all other supported OSes. + /// + [System.AttributeUsage(System.AttributeTargets.All)] + public class UnavailableAttribute : Attribute + { + public RuntimeOperatingSystem[] UnavailableOperatingSystems { get; protected set; } + + public UnavailableAttribute(params RuntimeOperatingSystem[] unavailableOperatingSystems) + { + UnavailableOperatingSystems = new RuntimeOperatingSystem[unavailableOperatingSystems.Length]; + unavailableOperatingSystems.CopyTo(UnavailableOperatingSystems, 0); } } diff --git a/plug-ins/Apple.Core/Apple.Core_Unity/Assets/Apple.Core/Runtime/RuntimeEnvironment.cs b/plug-ins/Apple.Core/Apple.Core_Unity/Assets/Apple.Core/Runtime/RuntimeEnvironment.cs index 6a91ef14..17bec381 100644 --- a/plug-ins/Apple.Core/Apple.Core_Unity/Assets/Apple.Core/Runtime/RuntimeEnvironment.cs +++ b/plug-ins/Apple.Core/Apple.Core_Unity/Assets/Apple.Core/Runtime/RuntimeEnvironment.cs @@ -1,5 +1,7 @@ using System; using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using UnityEngine; namespace Apple.Core { @@ -26,8 +28,10 @@ public RuntimeVersion(int major, int minor) Minor = minor; } - public override string ToString() => $"{Major}.{Minor}"; + public override string ToString() => (Minor == 0) ? $"{Major}" : $"{Major}.{Minor}"; + static readonly Regex _versionStringFormat = new Regex(@"^((?:\d+)(?:\.\d+)?)$"); + /// /// Accepted string formats are "Major.Minor" or "Major" where Major and Minor are represented by integer values. /// Minor value is assumed to be 0 when no Minor value is provided in the format string. @@ -44,39 +48,35 @@ public RuntimeVersion(int major, int minor) return null; } - string[] vStrings = versionString.Split('.', 3); - - // String provided in the format: "Major.Minor" - if (vStrings.Length >= 2) + // Ensure strings are formatted as "Major.Minor" or "Major" where Major and Minor are strings of numbers, e.g. "12.5" or "14" + if (_versionStringFormat.IsMatch(versionString)) { int major = 0, minor = 0; - if (Int32.TryParse(vStrings[0], out major) && Int32.TryParse(vStrings[1], out minor)) - { - return new RuntimeVersion(major, minor); - } - else - { - return null; - } - } - // String provided in the format: "Major" - else if (vStrings.Length == 1) - { - int major = 0; - - if (Int32.TryParse(vStrings[0], out major)) + // Get first string of numerals and try to parse + Match currMatch = Regex.Match(versionString, @"\d+"); + if (currMatch.Success && Int32.TryParse(currMatch.Value, out major)) { - return new RuntimeVersion(major, 0); + // Get the string of numerals, if they exist, and try to parse + currMatch = currMatch.NextMatch(); + if (currMatch.Success && Int32.TryParse(currMatch.Value, out minor)) + { + return new RuntimeVersion(major, minor); + } + else + { + return new RuntimeVersion(major, 0); + } } else { + Debug.Log($"[Apple.Core Plug-In] RuntimeEnvironment failed to parse \"{currMatch.Value}\" as Int32."); return null; } } - // Unsupported formatting. - else + else { + Debug.Log($"[Apple.Core Plug-In] RuntimeEnvironment failed to recognize \"{versionString}\" as a valid version string."); return null; } }