-
Notifications
You must be signed in to change notification settings - Fork 358
Fix parsing issue for Flags enum values with combined flags #3324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 33 commits
423924c
dae4b68
2b83a3a
cbc1745
58a8120
67dd391
8770f96
32067ec
e6f6da7
320caac
15406d1
63e7772
10e1ad8
d0ad6ad
37dea34
cb22ea8
8d4c6c5
8840be9
34328c1
27d7b12
0a8d79e
65eb52a
d3ed770
29a92e1
bd2b914
1b9c55d
06b5b0d
d2f6940
8f60c6c
1de41d7
12c4a37
f7670d0
2c8cb0b
4e99c72
29003b8
c7987af
e642006
7bb192b
69a5751
186dd74
c9367e9
e70ba44
c77fdc9
e9ac11d
cbeb977
5c366d4
af55733
4ebed58
b9fd1c4
4d62939
d37e00b
fc73df2
25fd8fa
1a685ab
515fead
32f6795
6bde046
c0afc7f
f932250
07982fa
96a9435
d21c367
a5732ab
ed149b4
33896d5
8bf49e3
8e958e2
6c69bfa
a7f9292
d6309f8
41ad1ac
00e849e
2d9877a
56de19b
f99d034
aff7557
fbf4ac5
6e1f709
41baf73
9384bc6
831ce7b
171e219
01d083f
4e69342
84e269b
7e44588
bc0eb18
4fdbd79
43293b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,8 @@ | |
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Diagnostics; | ||
| using System.Linq; | ||
| using System.Text; | ||
| using Microsoft.OData.Edm; | ||
| using Microsoft.OData.UriParser; | ||
|
|
||
|
|
@@ -152,17 +154,150 @@ public static bool TryParse(this IEdmEnumType enumType, long value, out IEdmEnum | |
| /// <param name="memberName">The member name to check.</param> | ||
| /// <param name="comparison">The comparison type to use for string comparison. Default is Ordinal.</param> | ||
| /// <returns>True if the member name exists in the enum type; otherwise, false.</returns> | ||
| public static bool ContainsMember(this IEdmEnumType enumType, string memberName, StringComparison comparison = StringComparison.Ordinal) | ||
| public static bool HasMember(this IEdmEnumType enumType, string memberName, StringComparison comparison = StringComparison.Ordinal) | ||
| { | ||
| return enumType.HasMember(memberName.AsSpan(), comparison); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Determines whether the specified enum type contains a member with the given name, using the specified string comparison. | ||
| /// </summary> | ||
| /// <param name="enumType">The <see cref="IEdmEnumType"/> to search for the member.</param> | ||
| /// <param name="memberName">The name of the member to locate within the enum type.</param> | ||
| /// <param name="exactMemberName">When this method returns, contains the <see cref="IEdmEnumMember"/> that matches the specified name, if a match is found; otherwise, null.</param> | ||
| /// <param name="comparison">The comparison type to use for string comparison. Default is Ordinal.</param> | ||
| /// <returns>True if the member name exists in the enum type; otherwise, false.</returns> | ||
| public static IEdmEnumMember FindMember(this IEdmEnumType enumType, string memberName, StringComparison comparison = StringComparison.Ordinal) | ||
| { | ||
| return enumType.FindMember(memberName.AsSpan(), comparison); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Checks if the given member name exists in the enum type. | ||
| /// </summary> | ||
| /// <param name="enumType">The enum type to search for the member.</param> | ||
| /// <param name="memberName">The name of the member to locate, represented as a <see cref="ReadOnlySpan{T}"/> of characters.</param> | ||
| /// <param name="comparison">The <see cref="StringComparison"/> to use when comparing the member names. The default is <see cref="StringComparison.Ordinal"/>.</param> | ||
| /// <returns>True if the member name exists in the enum type; otherwise, false.</returns> | ||
| public static bool HasMember(this IEdmEnumType enumType, ReadOnlySpan<char> memberName, StringComparison comparison = StringComparison.Ordinal) | ||
| { | ||
| foreach (IEdmEnumMember member in enumType.Members) | ||
| { | ||
| if (string.Equals(member.Name, memberName, comparison)) | ||
| if (memberName.Equals(member.Name.AsSpan(), comparison)) | ||
| { | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Checks if the given member name exists in the enum type. | ||
| /// </summary> | ||
| /// <param name="enumType">The enum type to search for the member.</param> | ||
| /// <param name="memberName">The name of the member to locate, represented as a <see cref="ReadOnlySpan{T}"/> of characters.</param> | ||
| /// <param name="exactMemberName">When this method returns, contains the <see cref="IEdmEnumMember"/> that matches the specified name, if a match is found; otherwise, null.</param> | ||
| /// <param name="comparison">The <see cref="StringComparison"/> to use when comparing the member names. The default is <see cref="StringComparison.Ordinal"/>.</param> | ||
| /// <returns>True if the member name exists in the enum type; otherwise, false.</returns> | ||
| public static IEdmEnumMember FindMember(this IEdmEnumType enumType, ReadOnlySpan<char> memberName, StringComparison comparison = StringComparison.Ordinal) | ||
| { | ||
| foreach (IEdmEnumMember member in enumType.Members) | ||
| { | ||
| if (memberName.Equals(member.Name.AsSpan(), comparison)) | ||
| { | ||
| return member; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Parses the specified integral value into a comma-separated string of flag names based on the members of the given EDM enum type. | ||
| /// </summary> | ||
| /// <param name="enumType">The EDM enum type containing the members to parse.</param> | ||
| /// <param name="value">The integral value to parse into flag names.</param> | ||
| /// <returns>A comma-separated string of flag names corresponding to the set bits in the specified value. Returns null otherwise.</returns> | ||
| public static string ParseFlagsFromIntegralValue(this IEdmEnumType enumType, long value) | ||
| { | ||
| var result = new List<string>(); | ||
| long remaining = value; | ||
gathogojr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| for (int index = enumType.Members.Count() - 1; index >= 0; index--) | ||
|
||
| { | ||
| IEdmEnumMember member = enumType.Members.ElementAt(index); | ||
| long flagValue = Convert.ToInt64(member.Value.Value); | ||
| if (flagValue != 0 && (remaining & flagValue) == flagValue) | ||
gathogojr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| result.Add(member.Name); | ||
| remaining &= ~flagValue; // Remove matched bits | ||
| } | ||
| } | ||
|
|
||
| return result.Count > 0 && remaining == 0 ? string.Join(", ", result.Reverse<string>()) : null; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Parses a comma-separated string of enum member names into a validated, formatted string containing only valid members of the specified <see cref="IEdmEnumType"/>. | ||
| /// </summary> | ||
| /// <param name="enumType">The EDM enum type to validate the enum member names against.</param> | ||
| /// <param name="memberName">A comma-separated string containing the names of enum members to parse and validate.</param> | ||
| /// <param name="comparison">The <see cref="StringComparison"/> to use when comparing the provided member names against the enum type's | ||
| /// defined members.</param> | ||
| /// <returns>A formatted string containing the validated enum member names, separated by commas and trimmed of whitespace. Otherwise, null or empty string.</returns> | ||
| public static string ParseFlagsFromStringValue(this IEdmEnumType enumType, string memberName, StringComparison comparison) | ||
| { | ||
| var stringBuilder = new StringBuilder(); | ||
WanjohiSammy marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| int startIndex = 0, endIndex = 0; | ||
| while (endIndex < memberName.Length) | ||
| { | ||
| while (endIndex < memberName.Length && memberName[endIndex] != ',') | ||
| { | ||
| endIndex++; | ||
| } | ||
|
|
||
| ReadOnlySpan<char> currentValue = memberName.AsSpan()[startIndex..endIndex].Trim(); | ||
| IEdmEnumMember edmEnumMember = enumType.FindMember(currentValue, comparison); | ||
| if (edmEnumMember == null) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| if (stringBuilder.Length > 0) | ||
| { | ||
| stringBuilder.Append(", "); | ||
WanjohiSammy marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| stringBuilder.Append(edmEnumMember.Name); | ||
| startIndex = endIndex + 1; | ||
| endIndex = startIndex; | ||
| } | ||
|
|
||
| return stringBuilder.Length == 0 ? null : stringBuilder.ToString(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Determines whether the specified integral value is a valid combination of flags for the given enumeration type. | ||
| /// </summary> | ||
| /// <param name="enumType">The enumeration type to validate against. Must represent a flags enumeration.</param> | ||
| /// <param name="memberIntegralValue">The integral value to validate as a combination of flags.</param> | ||
| /// <returns><see langword="true"/> if the specified value is a valid combination of the flags defined in the | ||
| /// enumeration; otherwise, <see langword="false"/>.</returns> | ||
| public static bool IsValidFlagsEnumValue(this IEdmEnumType enumType, long memberIntegralValue) | ||
| { | ||
| if(enumType == null || !enumType.IsFlags) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| long allFlagsMask = 0; | ||
| foreach (IEdmEnumMember member in enumType.Members) | ||
| { | ||
WanjohiSammy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| allFlagsMask |= (long)member.Value.Value; | ||
| } | ||
|
|
||
| return (memberIntegralValue & ~allFlagsMask) == 0; | ||
| } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.