Files
certmgr/certmgr/Core/Utils/Extenders.cs
2025-10-18 21:43:09 +02:00

249 lines
6.7 KiB
C#

using System.Reflection;
using System.Text;
namespace CertMgr.Core.Utils;
internal static class Extenders
{
private static readonly Dictionary<Type, string> _typeAliases = new Dictionary<Type, string>
{
{ typeof(long), "long" },
{ typeof(ulong), "ulong" },
{ typeof(int), "int" },
{ typeof(uint), "uint" },
{ typeof(short), "short" },
{ typeof(ushort), "ushort" },
{ typeof(byte), "byte" },
{ typeof(sbyte), "sbyte" },
{ typeof(double), "double" },
{ typeof(float), "float" },
{ typeof(decimal), "decimal" },
{ typeof(char), "char" },
{ typeof(string), "string" },
{ typeof(void), "void" },
{ typeof(bool), "bool" },
{ typeof(object), "object" },
};
public static string ToSeparatedList<T>(this IEnumerable<T> items, Func<T, string> formatter, string itemSeparator, string? lastItemSeparator = null)
{
using StringBuilderCache.ScopedBuilder lease = StringBuilderCache.AcquireScoped();
StringBuilder sb = lease.Builder;
ToSeparatedList(items, sb, formatter, itemSeparator, lastItemSeparator);
return sb.ToString();
}
public static void ToSeparatedList<T>(this IEnumerable<T> items, StringBuilder sb, Func<T, string> formatter, string itemSeparator, string? lastItemSeparator = null)
{
if (!items.Any())
{
return;
}
if (formatter == null)
{
formatter = item => item?.ToString() ?? "<null>";
}
lastItemSeparator = lastItemSeparator ?? itemSeparator;
using (IEnumerator<T> enu = items.GetEnumerator())
{
if (enu.MoveNext())
{
sb.Append(formatter(enu.Current));
bool hasNext = enu.MoveNext();
while (hasNext)
{
T current = enu.Current;
hasNext = enu.MoveNext();
sb.Append(hasNext ? itemSeparator : lastItemSeparator);
sb.Append(formatter(current));
}
}
}
}
public static string ToString(this Type type, bool includeNamespace)
{
if (type == null)
{
return null;
}
using StringBuilderCache.ScopedBuilder lease = StringBuilderCache.AcquireScoped();
StringBuilder sb = lease.Builder;
type.AppendStringType(sb, includeNamespace);
string typeString = sb.ToString();
return typeString;
}
private static void AppendStringType(this Type type, StringBuilder sb, bool includeNamespace)
{
if (type == null)
{
return;
}
if (type.IsGenericType)
{
if (includeNamespace)
{
sb.Append(type.Namespace);
sb.Append('.');
}
sb.Append(type.Name.Substring(0, type.Name.IndexOf('`')));
sb.Append('<');
Type[] genericArguments = type.GenericTypeArguments;
for (int i = 0; i < genericArguments.Length; i++)
{
if (i > 0)
{
sb.Append(',');
}
genericArguments[i].AppendStringType(sb, includeNamespace);
}
sb.Append('>');
}
else
{
if (_typeAliases.TryGetValue(type, out string? alias))
{
sb.Append(alias);
}
else
{
if (includeNamespace)
{
sb.Append(type.Namespace);
sb.Append('.');
}
sb.Append(type.Name);
}
}
}
public static bool Equivalent<T>(this IEnumerable<T?> left, IEnumerable<T?> right, IEqualityComparer<T?>? comparer = null) where T : notnull
{
if (ReferenceEquals(left, right))
{
return true;
}
if (left == null || right == null)
{
return false;
}
if (left.TryGetCount(out int lcount) && right.TryGetCount(out int rcount))
{
if (lcount != rcount)
{
return false;
}
}
int nullCount = 0;
Dictionary<T, int> cnt = new Dictionary<T, int>(comparer ?? EqualityComparer<T?>.Default);
foreach (T? item in left)
{
if (item == null)
{
nullCount++;
continue;
}
if (cnt.TryGetValue(item, out int value))
{
cnt[item] = ++value;
}
else
{
cnt.Add(item, 1);
}
}
foreach (T? item in right)
{
if (item == null)
{
nullCount--;
continue;
}
if (cnt.ContainsKey(item))
{
cnt[item]--;
}
else
{
return false;
}
}
bool equals = nullCount == 0 && cnt.Values.All(c => c == 0);
return equals;
}
private static bool TryGetCount<T>(this IEnumerable<T> items, out int count)
{
count = -1;
bool success = false;
if (items is ICollection<T> colt)
{
count = colt.Count;
success = true;
}
else if (items is System.Collections.ICollection col)
{
count = col.Count;
success = true;
}
else if (items is IReadOnlyCollection<T> rocol)
{
count = rocol.Count;
success = true;
}
return success;
}
public static bool IsAnyOf<T>(this T value, params T[] availableValues) where T : struct
{
if (!typeof(T).IsEnum)
{
throw new Exception(string.Format("Expected that the type is enum, got '{0}'", typeof(T).ToString(false)));
}
bool isOneOf = false;
Attribute? flags = typeof(T).GetCustomAttribute(typeof(FlagsAttribute));
if (flags == null)
{
if (availableValues != null && availableValues.Length > 0)
{
isOneOf = availableValues.Any(av => value.Equals(av));
}
}
else
{
ulong v = Convert.ToUInt64(value);
foreach (T availableValue in availableValues)
{
ulong av = Convert.ToUInt64(availableValue);
if ((v & av) == v)
{
isOneOf = true;
break;
}
}
}
return isOneOf;
}
}