97 lines
3.0 KiB
C#

using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Text;
using SoulstormReplayReader.Core.Domain.Player;
using SoulstormReplayReader.Core.Models;
namespace SoulstormReplayReader.Core.Extensions;
public static class Extensions
{
public static void RequireInRange(this int num, int min, int max, string errorMsg)
{
if (num < min || num > max)
throw new ArgumentOutOfRangeException(errorMsg);
}
public static void Swap<T>(this IList<T> list, int i1, int i2)
{
(list[i1], list[i2]) = (list[i2], list[i1]);
}
public static Span<byte> TrimEnd(this Span<byte> span, byte val = 0)
{
var i = span.Length - 1;
while (i > 0 && span[i--] == val) ;
return span[..i];
}
public static ExBinaryReader NextAsciiStringMustEqual(this ExBinaryReader binReader, ReadOnlySpan<byte> text)
{
if (!binReader.IsNextAsciiStringEquals(text))
{
throw new Exception(Encoding.ASCII.GetString(text) + "Нарушение структуры файла. ");
}
return binReader;
}
public static bool IsNextAsciiStringEquals(this ExBinaryReader binReader, ReadOnlySpan<byte> textSpan)
{
var nextTextSpan = binReader.ReadBytes(stackalloc byte[textSpan.Length]);
if (textSpan.SequenceEqual(nextTextSpan))
{
return true;
}
return textSpan.Length == nextTextSpan.Length && SpansEqualInvariant(textSpan, nextTextSpan);
static bool SpansEqualInvariant(ReadOnlySpan<byte> span1, ReadOnlySpan<byte> span2)
{
for (var i = 0; i < span1.Length; i++)
{
if (span1[i] == span2[i])
continue;
var char1 = char.ToLower((char)span1[i]);
var char2 = char.ToLower((char)span2[i]);
if (char1 != char2)
{
return false;
}
}
return true;
}
}
public static ReplayColor ReadBgraToArgb(this ExBinaryReader binReader)
{
var bgra = binReader.ReadUInt32();
var argb = ReverseBytes(bgra);
return Unsafe.As<uint, ReplayColor>(ref argb);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint ReverseBytes(uint value) =>
((value & 0x000000FFU) << 24) | ((value & 0x0000FF00U) << 8) |
((value & 0x00FF0000U) >> 8) | ((value & 0xFF000000U) >> 24);
public static string ToContentString(this IEnumerable<byte> bytes) =>
string.Join(' ',
bytes.Select(b => $"{b:x}".PadLeft(2, '0'))
);
[Conditional("DEBUGLOGGING")]
public static void LogPlayers(this List<PlayerModel> players)
{
Console.WriteLine("NAME TEAM TYPE RACE");
foreach (var pl in players.Where(p => p != null))
{
Console.WriteLine($"{pl.Name ?? "",-15} {pl.Team,-8} {pl.RawType} {pl.ResolvedType,-10} {pl.Race}");
}
}
}