mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-20 01:46:15 +00:00
some improvements (still broken)
This commit is contained in:
1 parent
ef329bfcbd
commit
5eba77dba9
6 files changed
+206
-119
No files matched your search
@@ -21,6 +21,12 @@ public class ExampleOptions2 : AbstractOptionGroup
|
||||
{
|
||||
ChangedEvent = x => Logger<ExamplePlugin>.Info($"changed Enum Opt to {x}"),
|
||||
};
|
||||
|
||||
public ModdedMultiSelectOption<TestingData> MultiSelectOption { get; } = new(
|
||||
"Emotions",
|
||||
TestingData.Happy,
|
||||
TestingData.All,
|
||||
TestingData.None);
|
||||
}
|
||||
|
||||
public enum TestingData : ulong
|
||||
@@ -28,4 +34,6 @@ public enum TestingData : ulong
|
||||
Happy,
|
||||
Sad,
|
||||
Neutral,
|
||||
All,
|
||||
None,
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||
using MiraAPI.Modules;
|
||||
using MiraAPI.Networking;
|
||||
using Reactor.Localization.Utilities;
|
||||
using Reactor.Utilities;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
@@ -49,10 +50,25 @@ public class ModdedMultiSelectOption<T> : ModdedOption<MultiSelectValue<T>> wher
|
||||
|
||||
data.Title = StringName;
|
||||
data.Type = global::OptionTypes.String;
|
||||
data.Values = (values is null
|
||||
? Enum.GetNames<T>()
|
||||
: values)
|
||||
.Select(CustomStringName.CreateAndRegister).ToArray();
|
||||
data.Values = (values ?? Enum.GetNames<T>()).Select(CustomStringName.CreateAndRegister).ToArray();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void BindConfig()
|
||||
{
|
||||
var entry = ParentMod?.GetConfigFile().Bind(ConfigDefinition, DefaultValue.ToString());
|
||||
if (entry != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Value = new MultiSelectValue<T>([.. entry.Value.Split(",").Select(x => Enum.Parse<T>(x.Trim()))]);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Value = DefaultValue;
|
||||
Logger<MiraApiPlugin>.Error($"Failed to bind config for {Title}: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -32,10 +32,8 @@ public abstract class ModdedOption<T> : IModdedOption where T : struct
|
||||
get => _parentMod;
|
||||
set
|
||||
{
|
||||
if (_parentMod != null || value == null) return;
|
||||
_parentMod = value;
|
||||
var entry = _parentMod.GetConfigFile().Bind(ConfigDefinition, DefaultValue);
|
||||
Value = entry.Value;
|
||||
BindConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +139,18 @@ public abstract class ModdedOption<T> : IModdedOption where T : struct
|
||||
StringOption stringOpt,
|
||||
Transform container);
|
||||
|
||||
/// <summary>
|
||||
/// Binds the option to the configuration file of the parent mod, if available.
|
||||
/// </summary>
|
||||
public virtual void BindConfig()
|
||||
{
|
||||
var entry = ParentMod?.GetConfigFile().Bind(ConfigDefinition, DefaultValue);
|
||||
if (entry != null)
|
||||
{
|
||||
Value = entry.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts the option to type of <typeparamref name="T"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using HarmonyLib;
|
||||
using MiraAPI.Utilities;
|
||||
using MonoMod.Utils;
|
||||
|
||||
namespace MiraAPI.Modules;
|
||||
|
||||
@@ -22,22 +19,22 @@ public struct MultiSelectValue<T>(params T[] values) : IEnumerable<T>, IEquatabl
|
||||
/// </summary>
|
||||
public string Values
|
||||
{
|
||||
readonly get => Helpers.Join(',', values);
|
||||
set => values = [.. value.TrueSplit(',').Select(Enum.Parse<T>)];
|
||||
readonly get => Helpers.Join(',', _values);
|
||||
set => _values = [.. value.TrueSplit(',').Select(Enum.Parse<T>)];
|
||||
}
|
||||
private HashSet<T> values = [.. values];
|
||||
private HashSet<T> _values = [.. values];
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of values contained within.
|
||||
/// </summary>
|
||||
public readonly int Count => values.Count;
|
||||
public readonly int Count => _values.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a single enum value to the end of the collection.
|
||||
/// </summary>
|
||||
/// <param name="item">The enum value to add.</param>
|
||||
/// <returns><c>true</c> if successfully added; otherwise, <c>false</c>.</returns>
|
||||
public readonly bool Add(T item) => values.Add(item);
|
||||
public readonly bool Add(T item) => _values.Add(item);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the first occurrence of the specified enum value.<br/>
|
||||
@@ -45,7 +42,7 @@ public struct MultiSelectValue<T>(params T[] values) : IEnumerable<T>, IEquatabl
|
||||
/// </summary>
|
||||
/// <param name="item">The enum value to remove.</param>
|
||||
/// <returns><c>true</c> if successfully removed; otherwise, <c>false</c>.</returns>
|
||||
public readonly bool Remove(T item) => values.Remove(item);
|
||||
public readonly bool Remove(T item) => _values.Remove(item);
|
||||
|
||||
/// <summary>
|
||||
/// Adds multiple enum values to the end of the collection.
|
||||
@@ -54,7 +51,7 @@ public struct MultiSelectValue<T>(params T[] values) : IEnumerable<T>, IEquatabl
|
||||
public readonly void AddRange(IEnumerable<T> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
values.Add(item);
|
||||
_values.Add(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -76,7 +73,7 @@ public struct MultiSelectValue<T>(params T[] values) : IEnumerable<T>, IEquatabl
|
||||
/// </summary>
|
||||
/// <param name="item">The enum value to locate.</param>
|
||||
/// <returns>true if the item is found in the collection; otherwise, false.</returns>
|
||||
public readonly bool Contains(T item) => values.Contains(item);
|
||||
public readonly bool Contains(T item) => _values.Contains(item);
|
||||
|
||||
/// <summary>
|
||||
/// Removes all enum values that match the specified predicate condition.<br/>
|
||||
@@ -100,43 +97,43 @@ public struct MultiSelectValue<T>(params T[] values) : IEnumerable<T>, IEquatabl
|
||||
/// <summary>
|
||||
/// Removes all enum values from the collection.
|
||||
/// </summary>
|
||||
public readonly void Clear() => values.Clear();
|
||||
public readonly void Clear() => _values.Clear();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the first value in the collection.
|
||||
/// </summary>
|
||||
/// <returns>Returns the first value.</returns>
|
||||
public readonly T First() => values.First();
|
||||
public readonly T First() => _values.First();
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the current instance to an array of bytes.
|
||||
/// </summary>
|
||||
/// <returns>An array of bytes representing the current instance.</returns>
|
||||
public readonly byte[] ToBytes() => Helpers.EnumsToBytes(this);
|
||||
public readonly byte[] ToBytes() => EnumSerializer.EnumsToBytes(this);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the collection to its string representation.
|
||||
/// </summary>
|
||||
/// <returns>A comma-separated string of enum values.</returns>
|
||||
public override readonly string ToString() => Values;
|
||||
public readonly override string ToString() => Values;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override readonly bool Equals(object? obj) => obj is MultiSelectValue<T> other && Equals(other);
|
||||
public readonly override bool Equals(object? obj) => obj is MultiSelectValue<T> other && Equals(other);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public readonly bool Equals(MultiSelectValue<T> other) => values.SetEquals(other.values);
|
||||
public readonly bool Equals(MultiSelectValue<T> other) => _values.SetEquals(other._values);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override readonly int GetHashCode() => Values?.GetHashCode() ?? 0;
|
||||
public readonly override int GetHashCode() => Values.GetHashCode();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public readonly IEnumerator<T> GetEnumerator() => ((IEnumerable<T>)values).GetEnumerator();
|
||||
public readonly IEnumerator<T> GetEnumerator() => ((IEnumerable<T>)_values).GetEnumerator();
|
||||
|
||||
/// <inheritdoc/>
|
||||
readonly IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public readonly void Dispose() => values.Clear();
|
||||
public readonly void Dispose() => _values.Clear();
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of <see cref="MultiSelectValue{T}"/> from the provided byte array.
|
||||
@@ -144,7 +141,7 @@ public struct MultiSelectValue<T>(params T[] values) : IEnumerable<T>, IEquatabl
|
||||
/// <param name="bytes">The bytes to deserialize from.</param>
|
||||
/// <returns>An instance of <see cref="MultiSelectValue{T}"/>.</returns>
|
||||
#pragma warning disable CA1000 // Do not declare static members on generic types
|
||||
public static MultiSelectValue<T> FromBytes(byte[] bytes) => new([.. Helpers.EnumsFromBytes<T>(bytes)]);
|
||||
public static MultiSelectValue<T> FromBytes(byte[] bytes) => new([.. EnumSerializer.EnumsFromBytes<T>(bytes)]);
|
||||
#pragma warning restore CA1000 // Do not declare static members on generic types
|
||||
|
||||
/// <summary>
|
||||
@@ -157,7 +154,7 @@ public struct MultiSelectValue<T>(params T[] values) : IEnumerable<T>, IEquatabl
|
||||
/// Converts the current instance to its array representation of values.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
public static implicit operator T[](MultiSelectValue<T> value) => [.. value.values];
|
||||
public static implicit operator T[](MultiSelectValue<T> value) => [.. value._values];
|
||||
|
||||
/// <summary>
|
||||
/// Converts the current instance to one singular value.
|
||||
@@ -167,7 +164,7 @@ public struct MultiSelectValue<T>(params T[] values) : IEnumerable<T>, IEquatabl
|
||||
#pragma warning disable S3877 // Exceptions should not be thrown from unexpected methods
|
||||
public static implicit operator T(MultiSelectValue<T> value) =>
|
||||
value.Count == 1
|
||||
? value.values.First()
|
||||
? value._values.First()
|
||||
: throw new ConversionFailException($"Tried to convert multiple or no values ({value.Values}) to a singular one");
|
||||
#pragma warning restore S3877 // Exceptions should not be thrown from unexpected methods
|
||||
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MiraAPI.Utilities;
|
||||
|
||||
/// <summary>
|
||||
/// Enum serializer for converting enums to and from byte arrays.
|
||||
/// </summary>
|
||||
public static class EnumSerializer
|
||||
{
|
||||
/// <summary>
|
||||
/// Serializes an enum to an array of bytes.
|
||||
/// </summary>
|
||||
/// <param name="value">The enum value to serialize.</param>
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <returns>A byte array representing the enum value.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown when the underlying type is not recognized.</exception>
|
||||
public static byte[] EnumToBytes<T>(T value) where T : struct, Enum
|
||||
{
|
||||
var underlyingType = typeof(T).GetEnumUnderlyingType();
|
||||
|
||||
return underlyingType switch
|
||||
{
|
||||
not null when underlyingType == typeof(byte) => [(byte)(object)value],
|
||||
not null when underlyingType == typeof(sbyte) => [(byte)(sbyte)(object)value],
|
||||
not null when underlyingType == typeof(short) => BitConverter.GetBytes((short)(object)value),
|
||||
not null when underlyingType == typeof(ushort) => BitConverter.GetBytes((ushort)(object)value),
|
||||
not null when underlyingType == typeof(int) => BitConverter.GetBytes((int)(object)value),
|
||||
not null when underlyingType == typeof(uint) => BitConverter.GetBytes((uint)(object)value),
|
||||
not null when underlyingType == typeof(long) => BitConverter.GetBytes((long)(object)value),
|
||||
not null when underlyingType == typeof(ulong) => BitConverter.GetBytes((ulong)(object)value),
|
||||
_ => throw new ArgumentException("Unknown underlying type for " + typeof(T).Name),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts bytes to an enum using the underlying type.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The byte array to convert.</param>
|
||||
/// <param name="offset">The offset in the byte array to start reading from.</param>
|
||||
/// <param name="underlyingType">The underlying type of the enum.</param>
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <returns>The enum value represented by the bytes.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown when the underlying type is not recognized.</exception>
|
||||
public static T EnumFromBytes<T>(byte[] bytes, int offset, Type underlyingType) where T : struct, Enum
|
||||
{
|
||||
return underlyingType switch
|
||||
{
|
||||
{ } t when t == typeof(byte) || t == typeof(sbyte) => (T)(object)bytes[offset],
|
||||
{ } t when t == typeof(short) => (T)(object)BitConverter.ToInt16(bytes, offset),
|
||||
{ } t when t == typeof(ushort) => (T)(object)BitConverter.ToUInt16(bytes, offset),
|
||||
{ } t when t == typeof(int) => (T)(object)BitConverter.ToInt32(bytes, offset),
|
||||
{ } t when t == typeof(uint) => (T)(object)BitConverter.ToUInt32(bytes, offset),
|
||||
{ } t when t == typeof(long) => (T)(object)BitConverter.ToInt64(bytes, offset),
|
||||
{ } t when t == typeof(ulong) => (T)(object)BitConverter.ToUInt64(bytes, offset),
|
||||
_ => throw new ArgumentException("Unknown underlying type for " + typeof(T).Name),
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EnumFromBytes{T}(byte[], int, Type)"/>
|
||||
public static T EnumFromBytes<T>(byte[] bytes, int offset) where T : struct, Enum => EnumFromBytes<T>(bytes, offset, typeof(T).GetEnumUnderlyingType());
|
||||
|
||||
/// <summary>
|
||||
/// Converts a byte array into a collection of enum values.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The byte array to convert.</param>
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <returns>An enumerable collection of enum values.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown when the byte array length is not a multiple of the enum's underlying type size.</exception>
|
||||
public static IEnumerable<T> EnumsFromBytes<T>(byte[] bytes) where T : struct, Enum
|
||||
{
|
||||
var underlyingType = typeof(T).GetEnumUnderlyingType();
|
||||
var size = GetManagedSize(underlyingType);
|
||||
|
||||
if (bytes.Length % size != 0)
|
||||
{
|
||||
throw new ArgumentException("Byte array length must be a multiple of " + size + ".");
|
||||
}
|
||||
|
||||
return EnumsFromBytesIterator<T>(bytes, underlyingType, size);
|
||||
}
|
||||
|
||||
private static IEnumerable<T> EnumsFromBytesIterator<T>(byte[] bytes, Type underlyingType, int size) where T : struct, Enum
|
||||
{
|
||||
var count = bytes.Length / size;
|
||||
var underlyingArray = Array.CreateInstance(underlyingType, count);
|
||||
Buffer.BlockCopy(bytes, 0, underlyingArray, 0, bytes.Length);
|
||||
|
||||
foreach (var value in underlyingArray)
|
||||
yield return (T)value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a collection of enum values to a byte array.
|
||||
/// </summary>
|
||||
/// <param name="values"> The collection of enum values to convert.</param>
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <returns>A byte array representing the collection of enum values.</returns>
|
||||
public static byte[] EnumsToBytes<T>(IEnumerable<T> values) where T : struct, Enum
|
||||
{
|
||||
var underlyingType = typeof(T).GetEnumUnderlyingType();
|
||||
var size = GetManagedSize(underlyingType);
|
||||
var valuesArray = values.ToArray();
|
||||
var count = valuesArray.Length;
|
||||
|
||||
var underlyingArray = Array.CreateInstance(underlyingType, count);
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
underlyingArray.SetValue(ConvertToUnderlyingType(valuesArray[i], underlyingType), i);
|
||||
}
|
||||
|
||||
var bytes = new byte[count * size];
|
||||
Buffer.BlockCopy(underlyingArray, 0, bytes, 0, bytes.Length);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private static object ConvertToUnderlyingType<T>(T value, Type underlyingType) where T : struct, Enum
|
||||
{
|
||||
return underlyingType switch
|
||||
{
|
||||
not null when underlyingType == typeof(byte) => (byte)(object)value,
|
||||
not null when underlyingType == typeof(sbyte) => (sbyte)(object)value,
|
||||
not null when underlyingType == typeof(short) => (short)(object)value,
|
||||
not null when underlyingType == typeof(ushort) => (ushort)(object)value,
|
||||
not null when underlyingType == typeof(int) => (int)(object)value,
|
||||
not null when underlyingType == typeof(uint) => (uint)(object)value,
|
||||
not null when underlyingType == typeof(long) => (long)(object)value,
|
||||
not null when underlyingType == typeof(ulong) => (ulong)(object)value,
|
||||
_ => throw new InvalidOperationException("Unsupported underlying type."),
|
||||
};
|
||||
}
|
||||
|
||||
private static int GetManagedSize(Type type)
|
||||
{
|
||||
return Type.GetTypeCode(type) switch
|
||||
{
|
||||
TypeCode.Byte or TypeCode.SByte => 1,
|
||||
TypeCode.Int16 or TypeCode.UInt16 => 2,
|
||||
TypeCode.Int32 or TypeCode.UInt32 => 4,
|
||||
TypeCode.Int64 or TypeCode.UInt64 => 8,
|
||||
_ => throw new ArgumentException("Unsupported underlying type: " + type.Name),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -431,93 +431,4 @@ public static class Helpers
|
||||
items.Do(x => result += $"{separator}{x}");
|
||||
return result[separator.Length..];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes an enum to an array of bytes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <param name="value">The value to serialize.</param>
|
||||
/// <returns>An array of bytes representing the enum value.</returns>
|
||||
/// <exception cref="ArgumentException">The enum type had an unknown underlying type.</exception>
|
||||
public static byte[] EnumToBytes<T>(T value) where T : struct, Enum
|
||||
{
|
||||
var enumType = typeof(T);
|
||||
var underlyingType = enumType.GetEnumUnderlyingType();
|
||||
|
||||
if (underlyingType == typeof(byte))
|
||||
return [Convert.ToByte(value, NumberFormatInfo.InvariantInfo)];
|
||||
else if (underlyingType == typeof(sbyte))
|
||||
return [(byte)Convert.ToSByte(value, NumberFormatInfo.InvariantInfo)];
|
||||
else if (underlyingType == typeof(short))
|
||||
return BitConverter.GetBytes(Convert.ToInt16(value, NumberFormatInfo.InvariantInfo));
|
||||
else if (underlyingType == typeof(ushort))
|
||||
return BitConverter.GetBytes(Convert.ToUInt16(value, NumberFormatInfo.InvariantInfo));
|
||||
else if (underlyingType == typeof(int))
|
||||
return BitConverter.GetBytes(Convert.ToInt32(value, NumberFormatInfo.InvariantInfo));
|
||||
else if (underlyingType == typeof(uint))
|
||||
return BitConverter.GetBytes(Convert.ToUInt32(value, NumberFormatInfo.InvariantInfo));
|
||||
else if (underlyingType == typeof(long))
|
||||
return BitConverter.GetBytes(Convert.ToInt64(value, NumberFormatInfo.InvariantInfo));
|
||||
else if (underlyingType == typeof(ulong))
|
||||
return BitConverter.GetBytes(Convert.ToUInt64(value, NumberFormatInfo.InvariantInfo));
|
||||
else
|
||||
throw new ArgumentException("Unknown underlying type for " + enumType.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an array of bytes to an enum using the provided offset and the enum's underlying type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <param name="bytes">The array of bytes to deserialize from.</param>
|
||||
/// <param name="offset">The index to convert from.</param>
|
||||
/// <param name="underlyingType">The underlying type of the enum type.</param>
|
||||
/// <returns>An enum value from the provided byte array.</returns>
|
||||
/// <exception cref="ArgumentException">The enum type had an unknown underlying type.</exception>
|
||||
public static T EnumFromBytes<T>(byte[] bytes, int offset, Type underlyingType) where T : struct, Enum // This version exists purely for performance and optimisation
|
||||
{
|
||||
var enumType = typeof(T);
|
||||
|
||||
if (underlyingType == typeof(byte) || underlyingType == typeof(sbyte))
|
||||
return (T)(object)bytes[offset];
|
||||
else if (underlyingType == typeof(short))
|
||||
return (T)(object)BitConverter.ToInt16(bytes, offset);
|
||||
else if (underlyingType == typeof(ushort))
|
||||
return (T)(object)BitConverter.ToUInt16(bytes, offset);
|
||||
else if (underlyingType == typeof(int))
|
||||
return (T)(object)BitConverter.ToInt32(bytes, offset);
|
||||
else if (underlyingType == typeof(uint))
|
||||
return (T)(object)BitConverter.ToUInt32(bytes, offset);
|
||||
else if (underlyingType == typeof(long))
|
||||
return (T)(object)BitConverter.ToInt64(bytes, offset);
|
||||
else if (underlyingType == typeof(ulong))
|
||||
return (T)(object)BitConverter.ToUInt64(bytes, offset);
|
||||
else
|
||||
throw new ArgumentException("Unknown underlying type for " + enumType.Name);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EnumFromBytes{T}(byte[], int, Type)"/>
|
||||
public static T EnumFromBytes<T>(byte[] bytes, int offset) where T : struct, Enum => EnumFromBytes<T>(bytes, offset, typeof(T).GetEnumUnderlyingType());
|
||||
|
||||
/// <summary>
|
||||
/// Converts the provided byte array into a collection of enum values.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <param name="bytes">The array of bytes to deserialize from.</param>
|
||||
/// <returns>A collection of enum values.</returns>
|
||||
public static IEnumerable<T> EnumsFromBytes<T>(byte[] bytes) where T : struct, Enum
|
||||
{
|
||||
var underlyingType = typeof(T).GetEnumUnderlyingType();
|
||||
var size = underlyingType.GetManagedSize();
|
||||
|
||||
for (var i = 0; i < bytes.Length; i += size)
|
||||
yield return EnumFromBytes<T>(bytes, i, underlyingType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a collection of enum values to an array of bytes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <param name="values">The values to serialize to bytes to.</param>
|
||||
/// <returns>An array of bytes serialized from the collection of enum values.</returns>
|
||||
public static byte[] EnumsToBytes<T>(IEnumerable<T> values) where T : struct, Enum => [.. values.Select(EnumToBytes).SelectMany(x => x)];
|
||||
}
|
||||
Reference in new issue
Block a user