public static bool IsEquivalent(this string s1, string s2, StringEquivalenceOptions options)
        {
            int idx1 = 0, idx2 = 0;

            if (string.Equals(s1, s2))
            {
                return(true);
            }

            if (string.IsNullOrWhiteSpace(s1) || string.IsNullOrWhiteSpace(s2))
            {
                return(false);
            }

            if (options.HasFlag(StringEquivalenceOptions.IgnoreLeadingSpaces))
            {
                SkipToNextNonSpace(s1, ref idx1);
                SkipToNextNonSpace(s2, ref idx2);
            }

            var caseInsensitive = options.HasFlag(StringEquivalenceOptions.CaseInsensitive);

            while (idx1 < s1.Length && idx2 < s2.Length)
            {
                if (options.HasFlag(StringEquivalenceOptions.MultipleSpacesAreEquivalent))
                {
                    var ws1 = JumpOverWhiteSpace(s1, ref idx1);
                    var ws2 = JumpOverWhiteSpace(s2, ref idx2);

                    if (ws1 ^ ws2)
                    {
                        return(false);
                    }
                }

                if (!((caseInsensitive || s1[idx1] == s2[idx2]) && (!caseInsensitive || char.ToUpperInvariant(s1[idx1]) == char.ToUpperInvariant(s2[idx2]))))
                {
                    return(false);
                }

                idx1++;
                idx2++;
            }

            if (!options.HasFlag(StringEquivalenceOptions.IgnoreTrailingSpaces))
            {
                return(idx1 == s1.Length && idx2 == s2.Length);
            }

            SkipToNextNonSpace(s1, ref idx1);
            SkipToNextNonSpace(s2, ref idx2);

            return(idx1 == s1.Length && idx2 == s2.Length);
        }
        public void IsEquivalent_GivenValues_ReturnsExpectedResult(
            string s1,
            string s2,
            StringEquivalenceOptions options,
            bool expectedValue)
        {
            var actualResult1 = s1.IsEquivalent(s2, options);

            Assert.AreEqual(expectedValue, actualResult1, $"\"{s1}\".IsEquivalant(\"{s2}\", {options}) ");

            // the order of the strings shouldn't matter, so we'll switch them round and do the test the other way
            var actualResult2 = s2.IsEquivalent(s1, options);

            Assert.AreEqual(expectedValue, actualResult2, $"\"{s2}\".IsEquivalant(\"{s1}\", {options}) ");
        }