From 43fd348fae4e150570eef1214a81215899a45718 Mon Sep 17 00:00:00 2001 From: Austin Noska Date: Tue, 13 Apr 2021 12:09:31 -0400 Subject: [PATCH] feat: Add enum extension method for cycling to next enum value --- CHANGELOG.md | 1 + .../Extensions/EnumExtensionsTest.cs | 12 ++++++++++ ICD.Common.Utils/Extensions/EnumExtensions.cs | 22 +++++++++++++++++++ ICD.Common.Utils/Extensions/ListExtensions.cs | 16 ++++++++++++++ 4 files changed, 51 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2b11fe..c7a1d62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added + - Added enum extension method for cycling to the next enum value - Added GetLocalTimeZoneName method to IcdEnvironment - Added MatchAny method to RegexUtils - Added OnSystemDeviceAddedRemoved and associated raise methods to IcdEnvironment for NETSTANDARD diff --git a/ICD.Common.Utils.Tests/Extensions/EnumExtensionsTest.cs b/ICD.Common.Utils.Tests/Extensions/EnumExtensionsTest.cs index d81f22c..0b94167 100644 --- a/ICD.Common.Utils.Tests/Extensions/EnumExtensionsTest.cs +++ b/ICD.Common.Utils.Tests/Extensions/EnumExtensionsTest.cs @@ -32,5 +32,17 @@ namespace ICD.Common.Utils.Tests.Extensions { Assert.AreEqual(expected, value.HasFlags(flags)); } + + [TestCase(eTestEnum.A, eTestEnum.B)] + [TestCase(eTestEnum.B, eTestEnum.C)] + [TestCase(eTestEnum.C, eTestEnum.A)] + [TestCase(eTestEnum.A | eTestEnum.B, null)] + public void CycleNextTest(eTestEnum value, eTestEnum? expected) + { + if (EnumUtils.HasMultipleFlags(value)) + Assert.Catch(typeof(InvalidOperationException), () => value.CycleNext()); + else + Assert.AreEqual(expected, value.CycleNext()); + } } } diff --git a/ICD.Common.Utils/Extensions/EnumExtensions.cs b/ICD.Common.Utils/Extensions/EnumExtensions.cs index 559bb7c..fbbb9d0 100644 --- a/ICD.Common.Utils/Extensions/EnumExtensions.cs +++ b/ICD.Common.Utils/Extensions/EnumExtensions.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using ICD.Common.Properties; namespace ICD.Common.Utils.Extensions @@ -83,5 +85,25 @@ namespace ICD.Common.Utils.Extensions { return EnumUtils.ToStringUndefined(extends); } + + /// + /// Returns the next defined enum value for the enum type. + /// + /// + /// + /// + public static T CycleNext(this T extends) + where T : struct, IConvertible + { + if (EnumUtils.IsFlagsEnum(typeof(T)) && !EnumUtils.HasSingleFlag(extends)) + throw new InvalidOperationException(string.Format("Cannot cycle enum with multiple flags - {0}", extends)); + + IEnumerable values = EnumUtils.GetValues(); + IList list = values as IList ?? values.ToArray(); + + int index = list.BinarySearch(extends); + + return index == list.Count - 1 ? list[0] : list[index + 1]; + } } } diff --git a/ICD.Common.Utils/Extensions/ListExtensions.cs b/ICD.Common.Utils/Extensions/ListExtensions.cs index dd41884..5646e17 100644 --- a/ICD.Common.Utils/Extensions/ListExtensions.cs +++ b/ICD.Common.Utils/Extensions/ListExtensions.cs @@ -349,6 +349,22 @@ namespace ICD.Common.Utils.Extensions #region Binary Search + /// + /// Returns the index of the item in the list. + /// + /// + /// + /// + /// + [PublicAPI] + public static int BinarySearch([NotNull] this IList extends, T item) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + return extends.BinarySearch(item, Comparer.Default); + } + /// /// Returns the index of the item in the list. ///