Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ValheimRadioMod v0.1.12
RadioMod\MonoMod.Backports.dll
Decompiled 8 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Buffers; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Threading; using Microsoft.CodeAnalysis; using MonoMod; using MonoMod.Backports.ILHelpers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: CLSCompliant(true)] [assembly: TargetFramework(".NETFramework,Version=v4.5.2", FrameworkDisplayName = ".NET Framework 4.5.2")] [assembly: AssemblyCompany("0x0ade, DaNike")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright 2024 0x0ade, DaNike")] [assembly: AssemblyDescription("A set of backports of new BCL features to all frameworks which MonoMod supports.")] [assembly: AssemblyFileVersion("1.1.2.0")] [assembly: AssemblyInformationalVersion("1.1.2+a1b82852b")] [assembly: AssemblyProduct("MonoMod.Backports")] [assembly: AssemblyTitle("MonoMod.Backports")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/MonoMod/MonoMod.git")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.2.0")] [assembly: TypeForwardedTo(typeof(ConcurrentBag<>))] [assembly: TypeForwardedTo(typeof(ConcurrentDictionary<, >))] [assembly: TypeForwardedTo(typeof(ConcurrentQueue<>))] [assembly: TypeForwardedTo(typeof(ConcurrentStack<>))] [assembly: TypeForwardedTo(typeof(EnumerablePartitionerOptions))] [assembly: TypeForwardedTo(typeof(IProducerConsumerCollection<>))] [assembly: TypeForwardedTo(typeof(OrderablePartitioner<>))] [assembly: TypeForwardedTo(typeof(Partitioner))] [assembly: TypeForwardedTo(typeof(Partitioner<>))] [assembly: TypeForwardedTo(typeof(IReadOnlyCollection<>))] [assembly: TypeForwardedTo(typeof(IReadOnlyList<>))] [assembly: TypeForwardedTo(typeof(IStructuralComparable))] [assembly: TypeForwardedTo(typeof(IStructuralEquatable))] [assembly: TypeForwardedTo(typeof(IntrospectionExtensions))] [assembly: TypeForwardedTo(typeof(IReflectableType))] [assembly: TypeForwardedTo(typeof(TypeDelegator))] [assembly: TypeForwardedTo(typeof(TypeInfo))] [assembly: TypeForwardedTo(typeof(CallerFilePathAttribute))] [assembly: TypeForwardedTo(typeof(CallerLineNumberAttribute))] [assembly: TypeForwardedTo(typeof(CallerMemberNameAttribute))] [assembly: TypeForwardedTo(typeof(ConditionalWeakTable<, >))] [assembly: TypeForwardedTo(typeof(TupleElementNamesAttribute))] [assembly: TypeForwardedTo(typeof(DefaultDllImportSearchPathsAttribute))] [assembly: TypeForwardedTo(typeof(DllImportSearchPath))] [assembly: TypeForwardedTo(typeof(SpinLock))] [assembly: TypeForwardedTo(typeof(SpinWait))] [assembly: TypeForwardedTo(typeof(ThreadLocal<>))] [assembly: TypeForwardedTo(typeof(Volatile))] [assembly: TypeForwardedTo(typeof(Tuple))] [assembly: TypeForwardedTo(typeof(Tuple<>))] [assembly: TypeForwardedTo(typeof(Tuple<, >))] [assembly: TypeForwardedTo(typeof(Tuple<, , >))] [assembly: TypeForwardedTo(typeof(Tuple<, , , >))] [assembly: TypeForwardedTo(typeof(Tuple<, , , , >))] [assembly: TypeForwardedTo(typeof(Tuple<, , , , , >))] [assembly: TypeForwardedTo(typeof(Tuple<, , , , , , >))] [assembly: TypeForwardedTo(typeof(Tuple<, , , , , , , >))] [assembly: TypeForwardedTo(typeof(ValueTuple))] [assembly: TypeForwardedTo(typeof(ValueTuple<>))] [assembly: TypeForwardedTo(typeof(ValueTuple<, >))] [assembly: TypeForwardedTo(typeof(ValueTuple<, , >))] [assembly: TypeForwardedTo(typeof(ValueTuple<, , , >))] [assembly: TypeForwardedTo(typeof(ValueTuple<, , , , >))] [assembly: TypeForwardedTo(typeof(ValueTuple<, , , , , >))] [assembly: TypeForwardedTo(typeof(ValueTuple<, , , , , , >))] [assembly: TypeForwardedTo(typeof(ValueTuple<, , , , , , , >))] [assembly: TypeForwardedTo(typeof(WeakReference<>))] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsByRefLikeAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NativeIntegerAttribute : Attribute { public readonly bool[] TransformFlags; public NativeIntegerAttribute() { TransformFlags = new bool[1] { true }; } public NativeIntegerAttribute(bool[] P_0) { TransformFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } internal static class AssemblyInfo { public const string AssemblyName = "MonoMod.Backports"; public const string AssemblyVersion = "1.1.2"; } namespace MonoMod.SourceGen.Attributes { [AttributeUsage(AttributeTargets.Class)] internal sealed class EmitILOverloadsAttribute : Attribute { public EmitILOverloadsAttribute(string filename, string kind) { } } internal static class ILOverloadKind { public const string Cursor = "ILCursor"; public const string Matcher = "ILMatcher"; } } namespace MonoMod.Backports { public static class MethodImplOptionsEx { public const MethodImplOptions Unmanaged = MethodImplOptions.Unmanaged; public const MethodImplOptions NoInlining = MethodImplOptions.NoInlining; public const MethodImplOptions ForwardRef = MethodImplOptions.ForwardRef; public const MethodImplOptions Synchronized = MethodImplOptions.Synchronized; public const MethodImplOptions NoOptimization = MethodImplOptions.NoOptimization; public const MethodImplOptions PreserveSig = MethodImplOptions.PreserveSig; public const MethodImplOptions AggressiveInlining = MethodImplOptions.AggressiveInlining; public const MethodImplOptions AggressiveOptimization = MethodImplOptions.AggressiveOptimization; public const MethodImplOptions InternalCall = MethodImplOptions.InternalCall; } } namespace System { public static class ArrayEx { private static class TypeHolder<T> { public static readonly T[] Empty = new T[0]; } public static int MaxLength => 1879048191; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T[] Empty<T>() { return TypeHolder<T>.Empty; } } public readonly struct SequencePosition : IEquatable<SequencePosition> { private readonly object? _object; private readonly int _integer; public SequencePosition(object? @object, int integer) { _object = @object; _integer = integer; } [EditorBrowsable(EditorBrowsableState.Never)] public object? GetObject() { return _object; } [EditorBrowsable(EditorBrowsableState.Never)] public int GetInteger() { return _integer; } public bool Equals(SequencePosition other) { if (_integer == other._integer) { return object.Equals(_object, other._object); } return false; } [EditorBrowsable(EditorBrowsableState.Never)] public override bool Equals(object? obj) { if (obj is SequencePosition other) { return Equals(other); } return false; } [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() { return HashCode.Combine(_object, _integer); } } public static class EnvironmentEx { public static int CurrentManagedThreadId => Environment.CurrentManagedThreadId; } public sealed class Gen2GcCallback : CriticalFinalizerObject { private readonly Func<bool>? _callback0; private readonly Func<object, bool>? _callback1; private GCHandle _weakTargetObj; private Gen2GcCallback(Func<bool> callback) { _callback0 = callback; } private Gen2GcCallback(Func<object, bool> callback, object targetObj) { _callback1 = callback; _weakTargetObj = GCHandle.Alloc(targetObj, GCHandleType.Weak); } public static void Register(Func<bool> callback) { new Gen2GcCallback(callback); } public static void Register(Func<object, bool> callback, object targetObj) { new Gen2GcCallback(callback, targetObj); } ~Gen2GcCallback() { if (_weakTargetObj.IsAllocated) { object target = _weakTargetObj.Target; if (target == null) { _weakTargetObj.Free(); return; } try { if (!_callback1(target)) { _weakTargetObj.Free(); return; } } catch { } } else { try { if (!_callback0()) { return; } } catch { } } GC.ReRegisterForFinalize(this); } } public struct HashCode { private static readonly uint s_seed = GenerateGlobalSeed(); private const uint Prime1 = 2654435761u; private const uint Prime2 = 2246822519u; private const uint Prime3 = 3266489917u; private const uint Prime4 = 668265263u; private const uint Prime5 = 374761393u; private uint _v1; private uint _v2; private uint _v3; private uint _v4; private uint _queue1; private uint _queue2; private uint _queue3; private uint _length; private static uint GenerateGlobalSeed() { Span<byte> destination = stackalloc byte[4]; using (RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create()) { byte[] array = new byte[destination.Length]; randomNumberGenerator.GetBytes(array); MemoryExtensions.AsSpan(array).CopyTo(destination); } return Unsafe.ReadUnaligned<uint>(ref destination[0]); } public static int Combine<T1>(T1 value1) { uint queuedValue = (uint)(value1?.GetHashCode() ?? 0); return (int)MixFinal(QueueRound(MixEmptyState() + 4, queuedValue)); } public static int Combine<T1, T2>(T1 value1, T2 value2) { uint queuedValue = (uint)(value1?.GetHashCode() ?? 0); uint queuedValue2 = (uint)(value2?.GetHashCode() ?? 0); return (int)MixFinal(QueueRound(QueueRound(MixEmptyState() + 8, queuedValue), queuedValue2)); } public static int Combine<T1, T2, T3>(T1 value1, T2 value2, T3 value3) { uint queuedValue = (uint)(value1?.GetHashCode() ?? 0); uint queuedValue2 = (uint)(value2?.GetHashCode() ?? 0); uint queuedValue3 = (uint)(value3?.GetHashCode() ?? 0); return (int)MixFinal(QueueRound(QueueRound(QueueRound(MixEmptyState() + 12, queuedValue), queuedValue2), queuedValue3)); } public static int Combine<T1, T2, T3, T4>(T1 value1, T2 value2, T3 value3, T4 value4) { uint input = (uint)(value1?.GetHashCode() ?? 0); uint input2 = (uint)(value2?.GetHashCode() ?? 0); uint input3 = (uint)(value3?.GetHashCode() ?? 0); uint input4 = (uint)(value4?.GetHashCode() ?? 0); Initialize(out var v, out var v2, out var v3, out var v4); v = Round(v, input); v2 = Round(v2, input2); v3 = Round(v3, input3); v4 = Round(v4, input4); return (int)MixFinal(MixState(v, v2, v3, v4) + 16); } public static int Combine<T1, T2, T3, T4, T5>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5) { uint input = (uint)(value1?.GetHashCode() ?? 0); uint input2 = (uint)(value2?.GetHashCode() ?? 0); uint input3 = (uint)(value3?.GetHashCode() ?? 0); uint input4 = (uint)(value4?.GetHashCode() ?? 0); uint queuedValue = (uint)(value5?.GetHashCode() ?? 0); Initialize(out var v, out var v2, out var v3, out var v4); v = Round(v, input); v2 = Round(v2, input2); v3 = Round(v3, input3); v4 = Round(v4, input4); return (int)MixFinal(QueueRound(MixState(v, v2, v3, v4) + 20, queuedValue)); } public static int Combine<T1, T2, T3, T4, T5, T6>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6) { uint input = (uint)(value1?.GetHashCode() ?? 0); uint input2 = (uint)(value2?.GetHashCode() ?? 0); uint input3 = (uint)(value3?.GetHashCode() ?? 0); uint input4 = (uint)(value4?.GetHashCode() ?? 0); uint queuedValue = (uint)(value5?.GetHashCode() ?? 0); uint queuedValue2 = (uint)(value6?.GetHashCode() ?? 0); Initialize(out var v, out var v2, out var v3, out var v4); v = Round(v, input); v2 = Round(v2, input2); v3 = Round(v3, input3); v4 = Round(v4, input4); return (int)MixFinal(QueueRound(QueueRound(MixState(v, v2, v3, v4) + 24, queuedValue), queuedValue2)); } public static int Combine<T1, T2, T3, T4, T5, T6, T7>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7) { uint input = (uint)(value1?.GetHashCode() ?? 0); uint input2 = (uint)(value2?.GetHashCode() ?? 0); uint input3 = (uint)(value3?.GetHashCode() ?? 0); uint input4 = (uint)(value4?.GetHashCode() ?? 0); uint queuedValue = (uint)(value5?.GetHashCode() ?? 0); uint queuedValue2 = (uint)(value6?.GetHashCode() ?? 0); uint queuedValue3 = (uint)(value7?.GetHashCode() ?? 0); Initialize(out var v, out var v2, out var v3, out var v4); v = Round(v, input); v2 = Round(v2, input2); v3 = Round(v3, input3); v4 = Round(v4, input4); return (int)MixFinal(QueueRound(QueueRound(QueueRound(MixState(v, v2, v3, v4) + 28, queuedValue), queuedValue2), queuedValue3)); } public static int Combine<T1, T2, T3, T4, T5, T6, T7, T8>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8) { uint input = (uint)(value1?.GetHashCode() ?? 0); uint input2 = (uint)(value2?.GetHashCode() ?? 0); uint input3 = (uint)(value3?.GetHashCode() ?? 0); uint input4 = (uint)(value4?.GetHashCode() ?? 0); uint input5 = (uint)(value5?.GetHashCode() ?? 0); uint input6 = (uint)(value6?.GetHashCode() ?? 0); uint input7 = (uint)(value7?.GetHashCode() ?? 0); uint input8 = (uint)(value8?.GetHashCode() ?? 0); Initialize(out var v, out var v2, out var v3, out var v4); v = Round(v, input); v2 = Round(v2, input2); v3 = Round(v3, input3); v4 = Round(v4, input4); v = Round(v, input5); v2 = Round(v2, input6); v3 = Round(v3, input7); v4 = Round(v4, input8); return (int)MixFinal(MixState(v, v2, v3, v4) + 32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4) { v1 = (uint)((int)s_seed + -1640531535 + -2048144777); v2 = s_seed + 2246822519u; v3 = s_seed; v4 = s_seed - 2654435761u; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint Round(uint hash, uint input) { return BitOperations.RotateLeft(hash + (uint)((int)input * -2048144777), 13) * 2654435761u; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint QueueRound(uint hash, uint queuedValue) { return BitOperations.RotateLeft(hash + (uint)((int)queuedValue * -1028477379), 17) * 668265263; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint MixState(uint v1, uint v2, uint v3, uint v4) { return BitOperations.RotateLeft(v1, 1) + BitOperations.RotateLeft(v2, 7) + BitOperations.RotateLeft(v3, 12) + BitOperations.RotateLeft(v4, 18); } private static uint MixEmptyState() { return s_seed + 374761393; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint MixFinal(uint hash) { hash ^= hash >> 15; hash *= 2246822519u; hash ^= hash >> 13; hash *= 3266489917u; hash ^= hash >> 16; return hash; } public void Add<T>(T value) { Add(value?.GetHashCode() ?? 0); } public void Add<T>(T value, IEqualityComparer<T>? comparer) { Add((value != null) ? (comparer?.GetHashCode(value) ?? value.GetHashCode()) : 0); } public void AddBytes(ReadOnlySpan<byte> value) { ref byte reference = ref MemoryMarshal.GetReference(value); ref byte reference2 = ref Unsafe.Add(ref reference, value.Length); while (Unsafe.ByteOffset(ref reference, ref reference2) >= 4) { Add(Unsafe.ReadUnaligned<int>(ref reference)); reference = ref Unsafe.Add(ref reference, 4); } while (Unsafe.IsAddressLessThan(ref reference, ref reference2)) { Add((int)reference); reference = ref Unsafe.Add(ref reference, 1); } } private void Add(int value) { uint num = _length++; switch (num % 4) { case 0u: _queue1 = (uint)value; return; case 1u: _queue2 = (uint)value; return; case 2u: _queue3 = (uint)value; return; } if (num == 3) { Initialize(out _v1, out _v2, out _v3, out _v4); } _v1 = Round(_v1, _queue1); _v2 = Round(_v2, _queue2); _v3 = Round(_v3, _queue3); _v4 = Round(_v4, (uint)value); } public int ToHashCode() { uint length = _length; uint num = length % 4; uint num2 = ((length < 4) ? MixEmptyState() : MixState(_v1, _v2, _v3, _v4)); num2 += length * 4; if (num != 0) { num2 = QueueRound(num2, _queue1); if (num > 1) { num2 = QueueRound(num2, _queue2); if (num > 2) { num2 = QueueRound(num2, _queue3); } } } return (int)MixFinal(num2); } [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes. Use ToHashCode to retrieve the computed hash code.", true)] [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() { throw new NotSupportedException("GetHashCode on HashCode is not supported"); } [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes.", true)] [EditorBrowsable(EditorBrowsableState.Never)] public override bool Equals(object? obj) { throw new NotSupportedException("Equals on HashCode is not supported"); } } public static class MathEx { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte Clamp(byte value, byte min, byte max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal Clamp(decimal value, decimal min, decimal max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Clamp(double value, double min, double max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short Clamp(short value, short min, short max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Clamp(int value, int min, int max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Clamp(long value, long min, long max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static nint Clamp(nint value, nint min, nint max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static sbyte Clamp(sbyte value, sbyte min, sbyte max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Clamp(float value, float min, float max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static ushort Clamp(ushort value, ushort min, ushort max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static uint Clamp(uint value, uint min, uint max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static ulong Clamp(ulong value, ulong min, ulong max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static nuint Clamp(nuint value, nuint min, nuint max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [DoesNotReturn] private static void ThrowMinMaxException<T>(T min, T max) { throw new ArgumentException($"Minimum {min} is less than maximum {max}"); } } [DebuggerTypeProxy(typeof(System.MemoryDebugView<>))] [DebuggerDisplay("{ToString(),raw}")] public readonly struct Memory<T> { private readonly object? _object; private readonly int _index; private readonly int _length; private const int RemoveFlagsBitMask = int.MaxValue; public static Memory<T> Empty => default(Memory<T>); public int Length => _length & 0x7FFFFFFF; public bool IsEmpty => (_length & 0x7FFFFFFF) == 0; public Span<T> Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { Span<T> result; if (_index < 0) { result = ((MemoryManager<T>)_object).GetSpan(); return result.Slice(_index & 0x7FFFFFFF, _length); } if (typeof(T) == typeof(char) && _object is string text) { result = new Span<T>(text, (IntPtr)RuntimeHelpers.OffsetToStringData, text.Length); return result.Slice(_index, _length); } if (_object != null) { return new Span<T>((T[])_object, _index, _length & 0x7FFFFFFF); } result = default(Span<T>); return result; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory(T[]? array) { if (array == null) { this = default(Memory<T>); return; } if (default(T) == null && array.GetType() != typeof(T[])) { System.ThrowHelper.ThrowArrayTypeMismatchException(); } _object = array; _index = 0; _length = array.Length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Memory(T[]? array, int start) { if (array == null) { if (start != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(); } this = default(Memory<T>); return; } if (default(T) == null && array.GetType() != typeof(T[])) { System.ThrowHelper.ThrowArrayTypeMismatchException(); } if ((uint)start > (uint)array.Length) { System.ThrowHelper.ThrowArgumentOutOfRangeException(); } _object = array; _index = start; _length = array.Length - start; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory(T[]? array, int start, int length) { if (array == null) { if (start != 0 || length != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(); } this = default(Memory<T>); return; } if (default(T) == null && array.GetType() != typeof(T[])) { System.ThrowHelper.ThrowArrayTypeMismatchException(); } if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start)) { System.ThrowHelper.ThrowArgumentOutOfRangeException(); } _object = array; _index = start; _length = length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Memory(MemoryManager<T> manager, int length) { if (length < 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(); } _object = manager; _index = int.MinValue; _length = length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Memory(MemoryManager<T> manager, int start, int length) { if (length < 0 || start < 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(); } _object = manager; _index = start | int.MinValue; _length = length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Memory(object? obj, int start, int length) { _object = obj; _index = start; _length = length; } public static implicit operator Memory<T>(T[]? array) { return new Memory<T>(array); } public static implicit operator Memory<T>(ArraySegment<T> segment) { return new Memory<T>(segment.Array, segment.Offset, segment.Count); } public static implicit operator ReadOnlyMemory<T>(Memory<T> memory) { return Unsafe.As<Memory<T>, ReadOnlyMemory<T>>(ref memory); } public override string ToString() { if (typeof(T) == typeof(char)) { if (!(_object is string text)) { return Span.ToString(); } return text.Substring(_index, _length & 0x7FFFFFFF); } return $"System.Memory<{typeof(T).Name}>[{_length & 0x7FFFFFFF}]"; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory<T> Slice(int start) { int length = _length; int num = length & 0x7FFFFFFF; if ((uint)start > (uint)num) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new Memory<T>(_object, _index + start, length - start); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory<T> Slice(int start, int length) { int length2 = _length; int num = length2 & 0x7FFFFFFF; if ((uint)start > (uint)num || (uint)length > (uint)(num - start)) { System.ThrowHelper.ThrowArgumentOutOfRangeException(); } return new Memory<T>(_object, _index + start, length | (length2 & int.MinValue)); } public void CopyTo(Memory<T> destination) { Span.CopyTo(destination.Span); } public bool TryCopyTo(Memory<T> destination) { return Span.TryCopyTo(destination.Span); } public unsafe MemoryHandle Pin() { if (_index < 0) { return ((MemoryManager<T>)_object).Pin(_index & 0x7FFFFFFF); } if (typeof(T) == typeof(char) && _object is string value) { GCHandle handle = GCHandle.Alloc(value, GCHandleType.Pinned); return new MemoryHandle(Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index), handle); } if (_object is T[] array) { if (_length < 0) { return new MemoryHandle(Unsafe.Add<T>(Unsafe.AsPointer(ref MemoryMarshal.GetReference<T>(array)), _index)); } GCHandle handle2 = GCHandle.Alloc(array, GCHandleType.Pinned); return new MemoryHandle(Unsafe.Add<T>((void*)handle2.AddrOfPinnedObject(), _index), handle2); } return default(MemoryHandle); } public T[] ToArray() { return Span.ToArray(); } [EditorBrowsable(EditorBrowsableState.Never)] public override bool Equals(object? obj) { if (obj is ReadOnlyMemory<T> readOnlyMemory) { return readOnlyMemory.Equals(this); } if (obj is Memory<T> other) { return Equals(other); } return false; } public bool Equals(Memory<T> other) { if (_object == other._object && _index == other._index) { return _length == other._length; } return false; } [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() { if (_object == null) { return 0; } return HashCode.Combine(_object, _index, _length); } } internal sealed class MemoryDebugView<T> { private readonly ReadOnlyMemory<T> _memory; [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public T[] Items => _memory.ToArray(); public MemoryDebugView(Memory<T> memory) { _memory = memory; } public MemoryDebugView(ReadOnlyMemory<T> memory) { _memory = memory; } } public static class MemoryExtensions { public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span) { return span.TrimStart().TrimEnd(); } public static ReadOnlySpan<char> TrimStart(this ReadOnlySpan<char> span) { int i; for (i = 0; i < span.Length && char.IsWhiteSpace(span[i]); i++) { } return span.Slice(i); } public static ReadOnlySpan<char> TrimEnd(this ReadOnlySpan<char> span) { int num = span.Length - 1; while (num >= 0 && char.IsWhiteSpace(span[num])) { num--; } return span.Slice(0, num + 1); } public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span, char trimChar) { return span.TrimStart(trimChar).TrimEnd(trimChar); } public static ReadOnlySpan<char> TrimStart(this ReadOnlySpan<char> span, char trimChar) { int i; for (i = 0; i < span.Length && span[i] == trimChar; i++) { } return span.Slice(i); } public static ReadOnlySpan<char> TrimEnd(this ReadOnlySpan<char> span, char trimChar) { int num = span.Length - 1; while (num >= 0 && span[num] == trimChar) { num--; } return span.Slice(0, num + 1); } public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars) { return span.TrimStart(trimChars).TrimEnd(trimChars); } public static ReadOnlySpan<char> TrimStart(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars) { if (trimChars.IsEmpty) { return span.TrimStart(); } int i; for (i = 0; i < span.Length; i++) { int num = 0; while (num < trimChars.Length) { if (span[i] != trimChars[num]) { num++; continue; } goto IL_003c; } break; IL_003c:; } return span.Slice(i); } public static ReadOnlySpan<char> TrimEnd(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars) { if (trimChars.IsEmpty) { return span.TrimEnd(); } int num; for (num = span.Length - 1; num >= 0; num--) { int num2 = 0; while (num2 < trimChars.Length) { if (span[num] != trimChars[num2]) { num2++; continue; } goto IL_0044; } break; IL_0044:; } return span.Slice(0, num + 1); } public static bool IsWhiteSpace(this ReadOnlySpan<char> span) { for (int i = 0; i < span.Length; i++) { if (!char.IsWhiteSpace(span[i])) { return false; } } return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOf<T>(this Span<T> span, T value) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value), span.Length); } if (typeof(T) == typeof(char)) { return System.SpanHelpers.IndexOf(ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, char>(ref value), span.Length); } return System.SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOf<T>(this Span<T> span, ReadOnlySpan<T> value) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), value.Length); } return System.SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOf<T>(this Span<T> span, T value) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value), span.Length); } if (typeof(T) == typeof(char)) { return System.SpanHelpers.LastIndexOf(ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, char>(ref value), span.Length); } return System.SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOf<T>(this Span<T> span, ReadOnlySpan<T> value) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), value.Length); } return System.SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool SequenceEqual<T>(this Span<T> span, ReadOnlySpan<T> other) where T : IEquatable<T> { int length = span.Length; if (default(T) != null && IsTypeComparableAsBytes<T>(out var size)) { if (length == other.Length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)), (nuint)length * size); } return false; } if (length == other.Length) { return System.SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length); } return false; } public static int SequenceCompareTo<T>(this Span<T> span, ReadOnlySpan<T> other) where T : IComparable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.SequenceCompareTo(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)), other.Length); } if (typeof(T) == typeof(char)) { return System.SpanHelpers.SequenceCompareTo(ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(other)), other.Length); } return System.SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(other), other.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOf<T>(this ReadOnlySpan<T> span, T value) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value), span.Length); } if (typeof(T) == typeof(char)) { return System.SpanHelpers.IndexOf(ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, char>(ref value), span.Length); } return System.SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOf<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> value) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), value.Length); } return System.SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOf<T>(this ReadOnlySpan<T> span, T value) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value), span.Length); } if (typeof(T) == typeof(char)) { return System.SpanHelpers.LastIndexOf(ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, char>(ref value), span.Length); } return System.SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOf<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> value) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), value.Length); } return System.SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAny<T>(this Span<T> span, T value0, T value1) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), span.Length); } return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAny<T>(this Span<T> span, T value0, T value1, T value2) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), Unsafe.As<T, byte>(ref value2), span.Length); } return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAny<T>(this Span<T> span, ReadOnlySpan<T> values) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)), values.Length); } return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), span.Length); } return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1, T value2) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), Unsafe.As<T, byte>(ref value2), span.Length); } return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> values) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)), values.Length); } return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny<T>(this Span<T> span, T value0, T value1) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), span.Length); } return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny<T>(this Span<T> span, T value0, T value1, T value2) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), Unsafe.As<T, byte>(ref value2), span.Length); } return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny<T>(this Span<T> span, ReadOnlySpan<T> values) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)), values.Length); } return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), span.Length); } return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1, T value2) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), Unsafe.As<T, byte>(ref value2), span.Length); } return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> values) where T : IEquatable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)), values.Length); } return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool SequenceEqual<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other) where T : IEquatable<T> { int length = span.Length; if (default(T) != null && IsTypeComparableAsBytes<T>(out var size)) { if (length == other.Length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)), (nuint)length * size); } return false; } if (length == other.Length) { return System.SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length); } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other) where T : IComparable<T> { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.SequenceCompareTo(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)), other.Length); } if (typeof(T) == typeof(char)) { return System.SpanHelpers.SequenceCompareTo(ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(other)), other.Length); } return System.SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(other), other.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool StartsWith<T>(this Span<T> span, ReadOnlySpan<T> value) where T : IEquatable<T> { int length = value.Length; if (default(T) != null && IsTypeComparableAsBytes<T>(out var size)) { if (length <= span.Length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), (nuint)length * size); } return false; } if (length <= span.Length) { return System.SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), length); } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool StartsWith<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> value) where T : IEquatable<T> { int length = value.Length; if (default(T) != null && IsTypeComparableAsBytes<T>(out var size)) { if (length <= span.Length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), (nuint)length * size); } return false; } if (length <= span.Length) { return System.SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), length); } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool EndsWith<T>(this Span<T> span, ReadOnlySpan<T> value) where T : IEquatable<T> { int length = span.Length; int length2 = value.Length; if (default(T) != null && IsTypeComparableAsBytes<T>(out var size)) { if (length2 <= length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), length - length2)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), (nuint)length2 * size); } return false; } if (length2 <= length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), length - length2), ref MemoryMarshal.GetReference(value), length2); } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool EndsWith<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> value) where T : IEquatable<T> { int length = span.Length; int length2 = value.Length; if (default(T) != null && IsTypeComparableAsBytes<T>(out var size)) { if (length2 <= length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), length - length2)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), (nuint)length2 * size); } return false; } if (length2 <= length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), length - length2), ref MemoryMarshal.GetReference(value), length2); } return false; } public static void Reverse<T>(this Span<T> span) { if (span.Length > 1) { ref T reference = ref MemoryMarshal.GetReference(span); ref T reference2 = ref Unsafe.Add(ref Unsafe.Add(ref reference, span.Length), -1); do { T val = reference; reference = reference2; reference2 = val; reference = ref Unsafe.Add(ref reference, 1); reference2 = ref Unsafe.Add(ref reference2, -1); } while (Unsafe.IsAddressLessThan(ref reference, ref reference2)); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span<T> AsSpan<T>(this T[]? array) { return new Span<T>(array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span<T> AsSpan<T>(this T[]? array, int start, int length) { return new Span<T>(array, start, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span<T> AsSpan<T>(this ArraySegment<T> segment) { return new Span<T>(segment.Array, segment.Offset, segment.Count); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span<T> AsSpan<T>(this ArraySegment<T> segment, int start) { if ((uint)start > segment.Count) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new Span<T>(segment.Array, segment.Offset + start, segment.Count - start); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span<T> AsSpan<T>(this ArraySegment<T> segment, int start, int length) { if ((uint)start > segment.Count) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } if ((uint)length > segment.Count - start) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.length); } return new Span<T>(segment.Array, segment.Offset + start, length); } public static Memory<T> AsMemory<T>(this T[]? array) { return new Memory<T>(array); } public static Memory<T> AsMemory<T>(this T[]? array, int start) { return new Memory<T>(array, start); } public static Memory<T> AsMemory<T>(this T[]? array, int start, int length) { return new Memory<T>(array, start, length); } public static Memory<T> AsMemory<T>(this ArraySegment<T> segment) { return new Memory<T>(segment.Array, segment.Offset, segment.Count); } public static Memory<T> AsMemory<T>(this ArraySegment<T> segment, int start) { if ((uint)start > segment.Count) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new Memory<T>(segment.Array, segment.Offset + start, segment.Count - start); } public static Memory<T> AsMemory<T>(this ArraySegment<T> segment, int start, int length) { if ((uint)start > segment.Count) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } if ((uint)length > segment.Count - start) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.length); } return new Memory<T>(segment.Array, segment.Offset + start, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyTo<T>(this T[]? source, Span<T> destination) { new ReadOnlySpan<T>(source).CopyTo(destination); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyTo<T>(this T[]? source, Memory<T> destination) { source.CopyTo(destination.Span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool Overlaps<T>(this Span<T> span, ReadOnlySpan<T> other) { return ((ReadOnlySpan<T>)span).Overlaps(other); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool Overlaps<T>(this Span<T> span, ReadOnlySpan<T> other, out int elementOffset) { return ((ReadOnlySpan<T>)span).Overlaps(other, out elementOffset); } public static bool Overlaps<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other) { if (span.IsEmpty || other.IsEmpty) { return false; } nint num = Unsafe.ByteOffset(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other)); if (Unsafe.SizeOf<IntPtr>() == 4) { if ((uint)(int)(IntPtr)num >= (uint)(span.Length * Unsafe.SizeOf<T>())) { return (uint)(int)(IntPtr)num > (uint)(-(other.Length * Unsafe.SizeOf<T>())); } return true; } if ((ulong)(long)(IntPtr)num >= (ulong)((long)span.Length * (long)Unsafe.SizeOf<T>())) { return (ulong)(long)(IntPtr)num > (ulong)(-((long)other.Length * (long)Unsafe.SizeOf<T>())); } return true; } public static bool Overlaps<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other, out int elementOffset) { if (span.IsEmpty || other.IsEmpty) { elementOffset = 0; return false; } nint num = Unsafe.ByteOffset(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other)); if (Unsafe.SizeOf<IntPtr>() == 4) { if ((uint)(int)(IntPtr)num < (uint)(span.Length * Unsafe.SizeOf<T>()) || (uint)(int)(IntPtr)num > (uint)(-(other.Length * Unsafe.SizeOf<T>()))) { if ((int)(IntPtr)num % Unsafe.SizeOf<T>() != 0) { System.ThrowHelper.ThrowArgumentException_OverlapAlignmentMismatch(); } elementOffset = (int)(IntPtr)num / Unsafe.SizeOf<T>(); return true; } elementOffset = 0; return false; } if ((ulong)(long)(IntPtr)num < (ulong)((long)span.Length * (long)Unsafe.SizeOf<T>()) || (ulong)(long)(IntPtr)num > (ulong)(-((long)other.Length * (long)Unsafe.SizeOf<T>()))) { if ((long)(IntPtr)num % Unsafe.SizeOf<T>() != 0L) { System.ThrowHelper.ThrowArgumentException_OverlapAlignmentMismatch(); } elementOffset = (int)((long)(IntPtr)num / Unsafe.SizeOf<T>()); return true; } elementOffset = 0; return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BinarySearch<T>(this Span<T> span, IComparable<T> comparable) { return span.BinarySearch<T, IComparable<T>>(comparable); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BinarySearch<T, TComparable>(this Span<T> span, TComparable comparable) where TComparable : IComparable<T> { return BinarySearch((ReadOnlySpan<T>)span, comparable); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BinarySearch<T, TComparer>(this Span<T> span, T value, TComparer comparer) where TComparer : IComparer<T> { return ((ReadOnlySpan<T>)span).BinarySearch(value, comparer); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BinarySearch<T>(this ReadOnlySpan<T> span, IComparable<T> comparable) { return MemoryExtensions.BinarySearch<T, IComparable<T>>(span, comparable); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BinarySearch<T, TComparable>(this ReadOnlySpan<T> span, TComparable comparable) where TComparable : IComparable<T> { return System.SpanHelpers.BinarySearch(span, comparable); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BinarySearch<T, TComparer>(this ReadOnlySpan<T> span, T value, TComparer comparer) where TComparer : IComparer<T> { if (comparer == null) { System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.comparer); } System.SpanHelpers.ComparerComparable<T, TComparer> comparable = new System.SpanHelpers.ComparerComparable<T, TComparer>(value, comparer); return BinarySearch(span, comparable); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool IsTypeComparableAsBytes<T>(out nuint size) { if (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte)) { size = 1u; return true; } if (typeof(T) == typeof(char) || typeof(T) == typeof(short) || typeof(T) == typeof(ushort)) { size = 2u; return true; } if (typeof(T) == typeof(int) || typeof(T) == typeof(uint)) { size = 4u; return true; } if (typeof(T) == typeof(long) || typeof(T) == typeof(ulong)) { size = 8u; return true; } size = 0u; return false; } public static Span<T> AsSpan<T>(this T[]? array, int start) { return Span<T>.Create(array, start); } public static bool Contains(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType) { return span.IndexOf(value, comparisonType) >= 0; } public static bool Equals(this ReadOnlySpan<char> span, ReadOnlySpan<char> other, StringComparison comparisonType) { switch (comparisonType) { case StringComparison.Ordinal: return span.SequenceEqual(other); case StringComparison.OrdinalIgnoreCase: if (span.Length != other.Length) { return false; } return EqualsOrdinalIgnoreCase(span, other); default: return span.ToString().Equals(other.ToString(), comparisonType); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool EqualsOrdinalIgnoreCase(ReadOnlySpan<char> span, ReadOnlySpan<char> other) { if (other.Length == 0) { return true; } return CompareToOrdinalIgnoreCase(span, other) == 0; } public static int CompareTo(this ReadOnlySpan<char> span, ReadOnlySpan<char> other, StringComparison comparisonType) { return comparisonType switch { StringComparison.Ordinal => span.SequenceCompareTo(other), StringComparison.OrdinalIgnoreCase => CompareToOrdinalIgnoreCase(span, other), _ => string.Compare(span.ToString(), other.ToString(), comparisonType), }; } private unsafe static int CompareToOrdinalIgnoreCase(ReadOnlySpan<char> strA, ReadOnlySpan<char> strB) { int num = Math.Min(strA.Length, strB.Length); int num2 = num; fixed (char* ptr = &MemoryMarshal.GetReference(strA)) { fixed (char* ptr3 = &MemoryMarshal.GetReference(strB)) { char* ptr2 = ptr; char* ptr4 = ptr3; while (num != 0 && *ptr2 <= '\u007f' && *ptr4 <= '\u007f') { int num3 = *ptr2; int num4 = *ptr4; if (num3 == num4) { ptr2++; ptr4++; num--; continue; } if ((uint)(num3 - 97) <= 25u) { num3 -= 32; } if ((uint)(num4 - 97) <= 25u) { num4 -= 32; } if (num3 != num4) { return num3 - num4; } ptr2++; ptr4++; num--; } if (num == 0) { return strA.Length - strB.Length; } num2 -= num; return string.Compare(strA.Slice(num2).ToString(), strB.Slice(num2).ToString(), StringComparison.OrdinalIgnoreCase); } } } public static int IndexOf(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType) { if (comparisonType == StringComparison.Ordinal) { return span.IndexOf(value); } return span.ToString().IndexOf(value.ToString(), comparisonType); } public static int ToLower(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo culture) { System.ThrowHelper.ThrowIfArgumentNull(culture, System.ExceptionArgument.culture); if (destination.Length < source.Length) { return -1; } string str = source.ToString(); AsSpan(culture.TextInfo.ToLower(str)).CopyTo(destination); return source.Length; } public static int ToLowerInvariant(this ReadOnlySpan<char> source, Span<char> destination) { return source.ToLower(destination, CultureInfo.InvariantCulture); } public static int ToUpper(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo culture) { System.ThrowHelper.ThrowIfArgumentNull(culture, System.ExceptionArgument.culture); if (destination.Length < source.Length) { return -1; } string str = source.ToString(); AsSpan(culture.TextInfo.ToUpper(str)).CopyTo(destination); return source.Length; } public static int ToUpperInvariant(this ReadOnlySpan<char> source, Span<char> destination) { return source.ToUpper(destination, CultureInfo.InvariantCulture); } public static bool EndsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType) { switch (comparisonType) { case StringComparison.Ordinal: return span.EndsWith(value); case StringComparison.OrdinalIgnoreCase: if (value.Length <= span.Length) { return EqualsOrdinalIgnoreCase(span.Slice(span.Length - value.Length), value); } return false; default: { string text = span.ToString(); string value2 = value.ToString(); return text.EndsWith(value2, comparisonType); } } } public static bool StartsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType) { switch (comparisonType) { case StringComparison.Ordinal: return span.StartsWith(value); case StringComparison.OrdinalIgnoreCase: if (value.Length <= span.Length) { return EqualsOrdinalIgnoreCase(span.Slice(0, value.Length), value); } return false; default: { string text = span.ToString(); string value2 = value.ToString(); return text.StartsWith(value2, comparisonType); } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan<char> AsSpan(this string? text) { if (text == null) { return default(ReadOnlySpan<char>); } return new ReadOnlySpan<char>(text, (IntPtr)RuntimeHelpers.OffsetToStringData, text.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan<char> AsSpan(this string? text, int start) { if (text == null) { if (start != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return default(ReadOnlySpan<char>); } if ((uint)start > (uint)text.Length) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new ReadOnlySpan<char>(text, (nint)RuntimeHelpers.OffsetToStringData + (nint)(start * 2), text.Length - start); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan<char> AsSpan(this string? text, int start, int length) { if (text == null) { if (start != 0 || length != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return default(ReadOnlySpan<char>); } if ((uint)start > (uint)text.Length || (uint)length > (uint)(text.Length - start)) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new ReadOnlySpan<char>(text, (nint)RuntimeHelpers.OffsetToStringData + (nint)(start * 2), length); } public static ReadOnlyMemory<char> AsMemory(this string? text) { if (text == null) { return default(ReadOnlyMemory<char>); } return new ReadOnlyMemory<char>(text, 0, text.Length); } public static ReadOnlyMemory<char> AsMemory(this string? text, int start) { if (text == null) { if (start != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return default(ReadOnlyMemory<char>); } if ((uint)start > (uint)text.Length) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new ReadOnlyMemory<char>(text, start, text.Length - start); } public static ReadOnlyMemory<char> AsMemory(this string? text, int start, int length) { if (text == null) { if (start != 0 || length != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return default(ReadOnlyMemory<char>); } if ((uint)start > (uint)text.Length || (uint)length > (uint)(text.Length - start)) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new ReadOnlyMemory<char>(text, start, length); } } [DebuggerTypeProxy(typeof(System.MemoryDebugView<>))] [DebuggerDisplay("{ToString(),raw}")] public readonly struct ReadOnlyMemory<T> { private readonly object? _object; private readonly int _index; private readonly int _length; internal const int RemoveFlagsBitMask = int.MaxValue; public static ReadOnlyMemory<T> Empty => default(ReadOnlyMemory<T>); public int Length => _length & 0x7FFFFFFF; public bool IsEmpty => (_length & 0x7FFFFFFF) == 0; public ReadOnlySpan<T> Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if (_index < 0) { return ((MemoryManager<T>)_object).GetSpan().Slice(_index & 0x7FFFFFFF, _length); } ReadOnlySpan<T> result; if (typeof(T) == typeof(char) && _object is string text) { result = new ReadOnlySpan<T>(text, (IntPtr)RuntimeHelpers.OffsetToStringData, text.Length); return result.Slice(_index, _length); } if (_object != null) { return new ReadOnlySpan<T>((T[])_object, _index, _length & 0x7FFFFFFF); } result = default(ReadOnlySpan<T>); return result; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory(T[]? array) { if (array == null) { this = default(ReadOnlyMemory<T>); return; } _object = array; _index = 0; _length = array.Length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory(T[]? array, int start, int length) { if (array == null) { if (start != 0 || length != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(); } this = default(ReadOnlyMemory<T>); return; } if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start)) { System.ThrowHelper.ThrowArgumentOutOfRangeException(); } _object = array; _index = start; _length = length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal ReadOnlyMemory(object? obj, int start, int length) { _object = obj; _index = start; _length = length; } public static implicit operator ReadOnlyMemory<T>(T[]? array) { return new ReadOnlyMemory<T>(array); } public static implicit operator ReadOnlyMemory<T>(ArraySegment<T> segment) { return new ReadOnlyMemory<T>(segment.Array, segment.Offset, segment.Count); } public override string ToString() { if (typeof(T) == typeof(char)) { if (!(_object is string text)) { return Span.ToString(); } return text.Substring(_index, _length & 0x7FFFFFFF); } return $"System.ReadOnlyMemory<{typeof(T).Name}>[{_length & 0x7FFFFFFF}]"; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory<T> Slice(int start) { int length = _length; int num = length & 0x7FFFFFFF; if ((uint)start > (uint)num) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new ReadOnlyMemory<T>(_object, _index + start, length - start); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory<T> Slice(int start, int length) { int length2 = _length; int num = _length & 0x7FFFFFFF; if ((uint)start > (uint)num || (uint)length > (uint)(num - start)) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new ReadOnlyMemory<T>(_object, _index + start, length | (length2 & int.MinValue)); } public void CopyTo(Memory<T> destination) { Span.CopyTo(destination.Span); } public bool TryCopyTo(Memory<T> destination) { return Span.TryCopyTo(destination.Span); } public unsafe MemoryHandle Pin() { if (_index < 0) { return ((MemoryManager<T>)_object).Pin(_index & 0x7FFFFFFF); } if (typeof(T) == typeof(char) && _object is string value) { GCHandle handle = GCHandle.Alloc(value, GCHandleType.Pinned); return new MemoryHandle(Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index), handle); } if (_object is T[] array) { if (_length < 0) { return new MemoryHandle(Unsafe.Add<T>(Unsafe.AsPointer(ref MemoryMarshal.GetReference<T>(array)), _index)); } GCHandle handle2 = GCHandle.Alloc(array, GCHandleType.Pinned); return new MemoryHandle(Unsafe.Add<T>((void*)handle2.AddrOfPinnedObject(), _index), handle2); } return default(MemoryHandle); } public T[] ToArray() { return Span.ToArray(); } [EditorBrowsable(EditorBrowsableState.Never)] public override bool Equals(object? obj) { if (obj is ReadOnlyMemory<T> other) { return Equals(other); } if (obj is Memory<T> memory) { return Equals(memory); } return false; } public bool Equals(ReadOnlyMemory<T> other) { if (_object == other._object && _index == other._index) { return _length == other._length; } return false; } [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() { if (_object == null) { return 0; } return HashCode.Combine(_object, _index, _length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal object? GetObjectStartLength(out int start, out int length) { start = _index; length = _length; return _object; } } [DebuggerTypeProxy(typeof(System.SpanDebugView<>))] [DebuggerDisplay("{ToString(),raw}")] public readonly ref struct ReadOnlySpan<T> { public ref struct Enumerator { private readonly ReadOnlySpan<T> _span; private int _index; public ref readonly T Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return ref _span[_index]; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Enumerator(ReadOnlySpan<T> span) { _span = span; _index = -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { int num = _index + 1; if (num < _span.Length) { _index = num; return true; } return false; } } private readonly object? _pinnable; private readonly IntPtr _byteOffset; private readonly int _length; public int Length => _length; public bool IsEmpty => _length == 0; public static ReadOnlySpan<T> Empty => default(ReadOnlySpan<T>); public ref readonly T this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if ((uint)index >= (uint)_length) { System.ThrowHelper.ThrowIndexOutOfRangeException(); } return ref Unsafe.Add(ref DangerousGetPinnableReference(), index); } } internal object? Pinnable => _pinnable; internal IntPtr ByteOffset => _byteOffset; public static bool operator !=(ReadOnlySpan<T> left, ReadOnlySpan<T> right) { return !(left == right); } [Obsolete("Equals() on ReadOnlySpan will always throw an exception. Use == instead.")] [EditorBrowsable(EditorBrowsableState.Never)] public override bool Equals(object? obj) { throw new NotSupportedException("Cannot call Equals on Span"); } [Obsolete("GetHashCode() on ReadOnlySpan will always throw an exception.")] [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() { throw new NotSupportedException("Cannot call GetHashCodee on Span"); } public static implicit operator ReadOnlySpan<T>(T[]? array) { return new ReadOnlySpan<T>(array); } public static implicit operator ReadOnlySpan<T>(ArraySegment<T> segment) { return new ReadOnlySpan<T>(segment.Array ?? throw new ArgumentNullException("segment"), segment.Offset, segment.Count); } public Enumerator GetEnumerator() { return new Enumerator(this); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpan(T[]? array) { if (array == null) { this = default(ReadOnlySpan<T>); return; } _length = array.Length; _pinnable = array; _byteOffset = System.SpanHelpers.PerTypeValues<T>.ArrayAdjustment; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpan(T[]? array, int start, int length) { if (array == null) { if (start != 0 || length != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } this = default(ReadOnlySpan<T>); return; } if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start)) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } _length = length; _pinnable = array; _byteOffset = System.SpanHelpers.PerTypeValues<T>.ArrayAdjustment.Add<T>(start); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public unsafe ReadOnlySpan(void* pointer, int length) { if (System.SpanHelpers.IsReferenceOrContainsReferences<T>()) { System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T)); } if (length < 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } _length = length; _pinnable = null; _byteOffset = new IntPtr(pointer); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal ReadOnlySpan(object? pinnable, IntPtr byteOffset, int length) { _length = length; _pinnable = pinnable; _byteOffset = byteOffset; } [EditorBrowsable(EditorBrowsableState.Never)] public unsafe ref readonly T GetPinnableReference() { if (_length != 0) { return ref DangerousGetPinnableReference(); } return ref Unsafe.AsRef<T>(null); } public void CopyTo(Span<T> destination) { if (!TryCopyTo(destination)) { System.ThrowHelper.ThrowArgumentException_DestinationTooShort(); } } public bool TryCopyTo(Span<T> destination) { int length = _length; int length2 = destination.Length; if (length == 0) { return true; } if ((uint)length > (uint)length2) { return false; } ref T src = ref DangerousGetPinnableReference(); System.SpanHelpers.CopyTo(ref destination.DangerousGetPinnableReference(), length2, ref src, length); return true; } public static bool operator ==(ReadOnlySpan<T> left, ReadOnlySpan<T> right) { if (left._length == right._length) { return Unsafe.AreSame(ref left.DangerousGetPinnableReference(), ref right.DangerousGetPinnableReference()); } return false; } public unsafe override string ToString() { if (typeof(T) == typeof(char)) { if (_byteOffset == (IntPtr)RuntimeHelpers.OffsetToStringData && Unsafe.As<object>(_pinnable) is string text && _length == text.Length) { return text; } fixed (char* value = &Unsafe.As<T, char>(ref DangerousGetPinnableReference())) { return new string(value, 0, _length); } } return $"System.ReadOnlySpan<{typeof(T).Name}>[{_length}]"; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpan<T> Slice(int start) { if ((uint)start > (uint)_length) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } IntPtr byteOffset = _byteOffset.Add<T>(start); int length = _length - start; return new ReadOnlySpan<T>(_pinnable, byteOffset, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpan<T> Slice(int start, int length) { if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start)) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } IntPtr byteOffset = _byteOffset.Add<T>(start); return new ReadOnlySpan<T>(_pinnable, byteOffset, length); } public T[] ToArray() { if (_length == 0) { return System.SpanHelpers.PerTypeValues<T>.EmptyArray; } T[] array = new T[_length]; CopyTo(array); return array; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal ref T DangerousGetPinnableReference() { return ref Unsafe.AddByteOffset(ref ILHelpers.ObjectAsRef<T>(_pinnable), _byteOffset); } } [DebuggerTypeProxy(typeof(System.SpanDebugView<>))] [DebuggerDisplay("{ToString(),raw}")] public readonly ref struct Span<T> { public ref struct Enumerator { private readonly Span<T> _span; private int _index; public ref T Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return ref _span[_index]; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Enumerator(Span<T> span) { _span = span; _index = -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { int num = _index + 1; if (num < _span.Length) { _index = num; return true; } return false; } } private readonly object? _pinnable; private readonly IntPtr _byteOffset; private readonly int _length; public int Length => _length; public bool IsEmpty => _length == 0; public static Span<T> Empty => default(Span<T>); public ref T this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if ((uint)index >= (uint)_length) { System.ThrowHelper.ThrowIndexOutOfRangeException(); } return ref Unsafe.Add(ref DangerousGetPinnableReference(), index); } } internal object? Pinnable => _pinnable; internal IntPtr ByteOffset => _byteOffset; public static bool operator !=(Span<T> left, Span<T> right) { return !(left == right); } [Obsolete("Equals() on Span will always throw an exception. Use == instead.")] [EditorBrowsable(EditorBrowsableState.Never)] public override bool Equals(object? obj) { throw new NotSupportedException("Cannot call Equals on Span"); } [Obsolete("GetHashCode() on Span will always throw an exception.")] [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() { throw new NotSupportedException("Cannot call GetHashCode on Span"); } public static implicit operator Span<T>(T[]? array) { return new Span<T>(array); } public static implicit operator Span<T>(ArraySegment<T> segment) { return new Span<T>(segment.Array, segment.Offset, segment.Count); } public Enumerator GetEnumerator() { return new Enumerator(this); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span(T[]? array) { if (array == null) { this = default(Span<T>); return; } if (default(T) == null && array.GetType() != typeof(T[])) { System.ThrowHelper.ThrowArrayTypeMismatchException(); } _length = array.Length; _pinnable = array; _byteOffset = System.SpanHelpers.PerTypeValues<T>.ArrayAdjustment; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Span<T> Create(T[]? array, int start) { if (array == null) { if (start != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return default(Span<T>); } if (default(T) == null && array.GetType() != typeof(T[])) { System.ThrowHelper.ThrowArrayTypeMismatchException(); } if ((uint)start > (uint)array.Length) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } IntPtr byteOffset = System.SpanHelpers.PerTypeValues<T>.ArrayAdjustment.Add<T>(start); int length = array.Length - start; return new Span<T>(array, byteOffset, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span(T[]? array, int start, int length) { if (array == null) { if (start != 0 || length != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } this = default(Span<T>); return; } if (default(T) == null && array.GetType() != typeof(T[])) { System.ThrowHelper.ThrowArrayTypeMismatchException(); } if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start)) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } _length = length; _pinnable = array; _byteOffset = System.SpanHelpers.PerTypeValues<T>.ArrayAdjustment.Add<T>(start); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public unsafe Span(void* pointer, int length) { if (System.SpanHelpers.IsReferenceOrContainsReferences<T>()) { System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T)); } if (length < 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } _length = length; _pinnable = null; _byteOffset = new IntPtr(pointer); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Span(object? pinnable, IntPtr byteOffset, int length) { _length = length; _pinnable = pinnable; _byteOffset = byteOffset; } [EditorBrowsable(EditorBrowsableState.Never)] public ref T GetPinnableReference() { if (_length != 0) { return ref DangerousGetPinnableReference(); } return ref Unsafe.NullRef<T>(); } public unsafe void Clear() { int length = _length; if (length == 0) { return; } nuint byteLength = (UIntPtr)(ulong)((uint)length * Unsafe.SizeOf<T>()); if ((Unsafe.SizeOf<T>() & (sizeof(IntPtr) - 1)) != 0) { if (_pinnable == null) { IntPtr byteOffset = _byteOffset; byte* ptr = (byte*)byteOffset.ToPointer(); System.SpanHelpers.ClearLessThanPointerSized(ptr, byteLength); } else { System.SpanHelpers.ClearLessThanPointerSized(ref Unsafe.As<T, byte>(ref DangerousGetPinnableReference()), byteLength); } } else if (System.SpanHelpers.IsReferenceOrContainsReferences<T>()) { nuint pointerSizeLength = (UIntPtr)(ulong)(length * Unsafe.SizeOf<T>() / sizeof(IntPtr)); System.SpanHelpers.ClearPointerSizedWithReferences(ref Unsafe.As<T, IntPtr>(ref DangerousGetPinnableReference()), pointerSizeLength); } else { System.SpanHelpers.ClearPointerSizedWithoutReferences(ref Unsafe.As<T, byte>(ref DangerousGetPinnableReference()), byteLength); } } public void Fill(T value) { int length = _length; if (length == 0) { return; } if (Unsafe.SizeOf<T>() == 1) { byte value2 = Unsafe.As<T, byte>(ref value); Unsafe.InitBlockUnaligned(ref Unsafe.As<T, byte>(ref DangerousGetPinnableReference()), value2, (uint)length); return; } ref T source = ref DangerousGetPinnableReference(); int i; for (i = 0; i < (length & -8); i += 8) { Unsafe.Add(ref source, i) = value; Unsafe.Add(ref source, i + 1) = value; Unsafe.Add(ref source, i + 2) = value; Unsafe.Add(ref source, i + 3) = value; Unsafe.Add(ref source, i + 4) = value; Unsafe.Add(ref source, i + 5) = value; Unsafe.Add(ref source, i + 6) = value; Unsafe.Add(ref source, i + 7) = value; } if (i < (length & -4)) { Unsafe.Add(ref source, i) = value; Unsafe.Add(ref source, i + 1) = value; Unsafe.Add(ref source, i + 2) = value; Unsafe.Add(ref source, i + 3) = value; i += 4; } for (; i < length; i++) { Unsafe.Add(ref source, i) = value; } } public void CopyTo(Span<T> destination) { if (!TryCopyTo(destination)) { System.ThrowHelper.ThrowArgumentException_DestinationTooShort(); } } public bool TryCopyTo(Span<T> destination) { int length = _length; int length2 = destination._length; if (length == 0) { return true; } if ((uint)length > (uint)length2) { return false; } ref T src = ref DangerousGetPinnableReference(); System.SpanHelpers.CopyTo(ref destination.DangerousGetPinnableReference(), length2, ref src, length); return true; } public static bool operator ==(Span<T> left, Span<T> right) { if (left._length == right._length) { return Unsafe.AreSame(ref left.DangerousGetPinnableReference(), ref right.DangerousGetPinnableReference()); } return false; } public static implicit operator ReadOnlySpan<T>(Span<T> span) { return new ReadOnlySpan<T>(span._pinnable, span._byteOffset, span._length); } public unsafe override string ToString() { if (typeof(T) == typeof(char)) { fixed (char* value = &Unsafe.As<T, char>(ref DangerousGetPinnableReference())) { return new string(value, 0, _length); } } return $"System.Span<{typeof(T).Name}>[{_length}]"; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span<T> Slice(int start) { if ((uint)start > (uint)_length) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } IntPtr byteOffset = _byteOffset.Add<T>(start); int length = _length - start; return new Span<T>(_pinnable, byteOffset, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span<T> Slice(int start, int length) { if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start)) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } IntPtr byteOffset = _byteOffset.Add<T>(start); return new Span<T>(_pinnable, byteOffset, length); } public T[] ToArray() { if (_length == 0) { return System.SpanHelpers.PerTypeValues<T>.EmptyArray; } T[] array = new T[_length]; CopyTo(array); return array; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal ref T DangerousGetPinnableReference() { return ref Unsafe.AddByteOffset(ref ILHelpers.ObjectAsRef<T>(_pinnable), _byteOffset); } } internal sealed class SpanDebugView<T> { private readonly T[] _array; [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public T[] Items => _array; public SpanDebugView(Span<T> span) { _array = span.ToArray(); } public SpanDebugView(ReadOnlySpan<T> span) { _array = span.ToArray(); } } internal static class SpanHelpers { internal struct ComparerComparable<T, TComparer> : IComparable<T> where TComparer : IComparer<T> { private readonly T _value; private readonly TComparer _comparer; public ComparerComparable(T value, TComparer comparer) { _value = value; _comparer = comparer; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int CompareTo(T? other) { return _comparer.Compare(_value, other); } } [StructLayout(LayoutKind.Sequential, Size = 64)] private struct Reg64 { } [StructLayout(LayoutKind.Sequential, Size = 32)] private struct Reg32 { } [StructLayout(LayoutKind.Sequential, Size = 16)] private struct Reg16 { } public static class PerTypeValues<T> { public static readonly bool IsReferenceOrContainsReferences = IsReferenceOrContainsReferencesCore(typeof(T)); public static readonly T[] EmptyArray = ArrayEx.Empty<T>(); public static readonly IntPtr ArrayAdjustment = MeasureArrayAdjustment(); private static IntPtr MeasureArrayAdjustment() { T[] array = new T[1]; return Unsafe.ByteOffset(ref ILHelpers.ObjectAsRef<T>((object)array), ref array[0]); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BinarySearch<T, TComparable>(this ReadOnlySpan<T> span, TComparable comparable) where TComparable : IComparable<T> { if (comparable == null) { System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.comparable); } return BinarySearch(ref MemoryMarshal.GetReference(span), span.Length, comparable); } public static int BinarySearch<T, TComparable>(ref T spanStart, int length, TComparable comparable) where TComparable : IComparable<T> { int num = 0; int num2 = length - 1; while (num <= num2) { int num3 = num2 + num >>> 1; ref TComparable reference = ref comparable; TComparable val = default(TComparable); if (val == null) { val = reference; reference = ref val; } int num4 = reference.CompareTo(Unsafe.Add(ref spanStart, num3)); if (num4 == 0) { return num3; } if (num4 > 0) { num = num3 + 1; } else { num2 = num3 - 1; } } return ~num; } public static int IndexOf(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength) { if (valueLength == 0) { return 0; } byte value2 = value; ref byte second = ref Unsafe.Add(ref value, 1); int num = valueLength - 1; int num2 = 0; while (true) { int num3 = searchSpaceLength - num2 - num; if (num3 <= 0) { break; } int num4 = IndexOf(ref Unsafe.Add(ref searchSpace, num2), value2, num3); if (num4 == -1) { break; } num2 += num4; if (SequenceEqual(ref Unsafe.Add(ref searchSpace, num2 + 1), ref second, num)) { return num2; } num2++; } return -1; } public static int IndexOfAny(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength) { if (valueLength == 0) { return 0; } int num = -1; for (int i = 0; i < valueLength; i++) { int num2 = IndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength); if ((uint)num2 < (uint)num) { num = num2; searchSpaceLength = num2; if (num == 0) { break; } } } return num; } public static int LastIndexOfAny(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength) { if (valueLength == 0) { return 0; } int num = -1; for (int i = 0; i < valueLength; i++) { int num2 = LastIndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength); if (num2 > num) { num = num2; } } return num; } public static int IndexOf(ref byte searchSpace, byte value, int length) { nint num = 0; nint num2 = length; while (true) { if ((nuint)num2 >= (nuint)8u) { num2 -= 8; if (value != Unsafe.AddByteOffset(ref searchSpace, num)) { if (value == Unsafe.AddByteOffset(ref searchSpace, num + 1)) { goto IL_0109; } if (value == Unsafe.AddByteOffset(ref searchSpace, num + 2)) { goto IL_010f; } if (value != Unsafe.AddByteOffset(ref searchSpace, num + 3)) { if (value != Unsafe.AddByteOffset(ref searchSpace, num + 4)) { if (value != Unsafe.AddByteOffset(ref searchSpace, num + 5)) { if (value != Unsafe.AddByteOffset(ref searchSpace, num + 6)) { if (value == Unsafe.AddByteOffset(ref searchSpace, num + 7)) { break; } num += 8; continue; } return (int)(num + 6); } return (int)(num + 5); } return (int)(num + 4); } goto IL_0115; } } else { if ((nuint)num2 >= (nuint)4u) { num2 -= 4; if (value == Unsafe.AddByteOffset(ref searchSpace, num)) { goto IL_0106; } if (value == Unsafe.AddByteOffset(ref searchSpace, num + 1)) { goto IL_0109; } if (value == Unsafe.AddByteOffset(ref searchSpace, num + 2)) { goto IL_010f; } if (value == Unsafe.AddByteOffset(ref searchSpace, num + 3)) { goto IL_0115; } num += 4; } while (true) { if (num2 != 0) { num2--; if (value == Unsafe.AddByteOffset(ref searchSpace, num)) { break; } num++; continue; } return -1; } } goto IL_0106; IL_010f: return (int)(num + 2); IL_0106: return (int)num; IL_0109: return (int)(num + 1); IL_0115: return (int)(num + 3); } return (int)(num + 7); } public static int LastIndexOf(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength) { if (valueLength == 0) { return 0; } byte value2 = value; ref byte second = ref Unsafe.Add(ref value, 1); int num = valueLength - 1; int num2 = 0; while (true) { int num3 = searchSpaceLength - num2 - num; if (num3 <= 0) { break; } int num4 = LastIndexOf(ref searchSpace, value2, num3); if (num4 == -1) { break; } if (SequenceEqual(ref Unsafe.Add(ref searchSpace, num4 + 1), ref second, num)) { return num4; } num2 += num3 - num4; } return -1; } public static int LastIndexOf(ref byte searchSpace, byte value, int length) { nint num = length; nint num2 = length; while (true) { if ((nuint)num2 >= (nuint)8u) { num2 -= 8; num -= 8; if (value == Unsafe.AddByteOffset(ref searchSpace, num + 7)) { break; } if (value == Unsafe.AddByteOffset(ref searchSpace, num + 6)) { return (int)(num + 6); } if (value == Unsafe.AddByteOffset(ref searchSpace, num + 5)) { return (int)(num + 5); } if (value == Unsafe.AddByteOffset(ref searchSpace, num + 4)) { return (int)(num + 4); } if (value == Unsafe.AddByteOffset(ref searchSpace, num + 3)) { goto IL_010f; } if (value == Unsafe.AddByteOffset(ref searchSpace, num + 2)) { goto IL_0109; } if (value == Unsafe.AddByteOffset(ref searchSpace, num + 1)) { goto IL_0103; } if (value != Unsafe.AddByteOffset(ref searchSpace, num)) { continue; } } else { if ((nuint)num2 >= (nuint)4u) { num2 -= 4; num -= 4; if (value == Unsafe.AddByteOffset(ref searchSpace, num + 3)) { goto IL_010f; } if (value == Unsafe.AddByteOffset(ref searchSpace, num + 2)) { goto IL_0109; } if (value == Unsafe.AddByteOffset(ref searchSpace, num + 1)) { goto IL_0103; } if (value == Unsafe.AddByteOffset(ref searchSpace, num)) { goto IL_0100; } } do { if (num2 != 0) { num2--; num--; continue; } return -1; } while (value != Unsafe.AddByteOffset(ref searchSpace, num)); } goto IL_0100; IL_0109: return (int)(num + 2); IL_010f: return (int)(num + 3); IL_0103: return (int)(num + 1); IL_0100: return (int)num; } return (int)(num + 7); } public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, int length) { nint num = 0; nint num2 = length; while (true) { if ((nuint)num2 >= (nuint)8u) { num2 -= 8; uint num3 = Unsafe.AddByteOffset(ref searchSpace, num); if (value0 != num3 && value1 != num3) { num3 = Unsafe.AddByteOffset(ref searchSpace, num + 1); if (value0 == num3 || value1 == num3) { goto IL_019b; } num3 = Unsafe.AddByteOffset(ref searchSpace, num + 2); if (value0 == num3 || value1 == num3) { goto IL_01a1; } num3 = Unsafe.AddByteOffset(ref searchSpace, num + 3); if (value0 != num3 && value1 != num3) { num3 = Unsafe.AddByteOffset(ref searchSpace, num + 4); if (value0 != num3 && value1 != num3) { num3 = Unsafe.AddByteOffset(ref searchSpace, num + 5); if (value0 != num3 && value1 != num3) { num3 = Unsafe.AddByteOffset(ref searchSpace, num + 6); if (value0 != num3 && value1 != num3) { num3 = Unsafe.AddByteOffset(ref searchSpace, num + 7); if (value0 == num3 || value1 == num3) { break; } num += 8; continue; } return (int)(num + 6); } return (int)(num + 5); } return (int)(num + 4); } goto IL_01a7; } } else { if ((nuint)num2 >= (nuint)4u) { num2 -= 4; uint num3 = Unsafe.AddByteOffset(ref searchSpace, num); if (value0 == num3 || value1 == num3) { goto IL_0198; } num3 = Unsafe.AddByteOffset(ref searchSpace, num + 1); if (value0 == num3 || value1 == num3) { goto IL_019b; } num3 = Unsafe.AddByteOffset(ref searchSpace, num + 2); if (value0 == num3 || value1 == num3) { goto IL_01a1; } num3 = Unsafe.AddByteOffset(ref searchSpace, num + 3); if (value0 == num3 || value1 == num3) { goto IL_01a7; } num += 4; } while (true) { if (num2 != 0) { num2--; uint num3 = Unsafe.AddByteOffset(ref searchSpace, num); if (value0 == num3 || value1 == num3) { break; } num++; continue; } return -1; } } goto IL_0198; IL_01a1: return (int)(num + 2); IL_019b: return (int)(num + 1); IL_01a7: return (int)(num + 3); IL_0198: return (int)num; } return (int)(num + 7); } public static int IndexOfAny(ref byte searchSpace, byte value0, byte value1, byte value2, int length) { nint num = 0; nint num2 = length; while (true) { if ((nuint)num2 >= (nuint)8u) { num2 -= 8; uint num3 = Unsafe.AddByteOffset(ref searchSpace, num); if (value0 != num3 && value1 != num3 && value2 != num3) { num3 = Unsafe.AddByteOffset(ref searchSpace, num + 1); if (value0 == num3 || value1 == num3 || value2 == num3) { goto IL_020a; } num3 = Unsafe.AddByteOffset(ref searchSpace, num + 2); if (value0 == num3 || value1 == num3 || value2 == num3) { goto IL_0210; } num3 = Unsafe.AddByteOffset(ref searchSpace, num + 3); if (value0 != num3 && value1 != num3 && value2 != num3) { num3 = Unsafe.AddByteOffset(ref searchSpace, num + 4); if (value0 != num3 && value1 != num3 && value2 != num3) { num3 = Unsafe.AddByteOffset(ref searchSpace, num + 5); if (value0 != num3 && value1 != num3 && value2 != num3) { num3 = Unsafe.AddByteOffset(ref searchSpace, num + 6); if (value0 != num3 && value1 != num3 && value2 != num3) { num3 = Unsafe.AddByteOffset(ref searchSpace, num + 7); if (value0 == num3 || value1 == num3 || value2 == num3) { break; } num += 8; continue; } return (int)(num + 6); } return (int)(num + 5); } return (int)(num + 4); } goto IL_0216; } } else { if ((nuint)num2 >= (nuint)4u) { num2 -= 4; uint num3 = Unsafe.AddByteOffset(ref searchSpace, num); if (value0 == num3 || value1 == num3 || value2 == num3) { goto IL_0207; } num3 = Unsafe.AddByteOffset(ref searchSpace, num + 1); if (value0 == num3 || value1 == num3 || value2 == num3) { goto IL_020a; } num3 = Unsafe.AddByteOffset(ref searchSpace, num + 2); if (value0 == num3 || value1 == num3 || value2 == num3) { goto IL_0210; } num3 = Unsafe.AddByteOffset(ref searchSpace, num + 3); if (value0 == num3 || value1 == num3 || value2 == num3) { goto IL_0216; } num += 4; } while (true) { if (num2 != 0) { num2--; uint num3 = Unsafe.AddByteOffset(ref searchSpace, num); if (value0 == num3 || value1 == num3 || value2 == num3) { break; } num++; continue; } return -1; } } goto IL_0207; IL_0207: return (int)num; IL_0210: return (int)(num + 2); IL_020a: return (int)(num + 1); IL_0216: return (int)(num + 3); } return (int)(num + 7); } public static int LastIndexOfAny(ref byte searchSpace, byte value0, byte value1, int length) { nint num = length; nint num2 = length; while (true) { if ((nuint)num2 >= (nuint)8u) { num2 -= 8; num -= 8; uint num3 = Unsafe.AddByteOffset(ref searchSpace, num + 7); if (value0 == num3 || value1 == num3) { break; } num3 = Unsafe.AddByteOffset(ref searchSpace, num + 6); if (value0 == num3 || value1 == nu
RadioMod\MonoMod.ILHelpers.dll
Decompiled 8 hours agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Microsoft.CodeAnalysis; [assembly: AssemblyMetadata("IsTrimmable", "True")] [assembly: AssemblyCopyright("Copyright 2024 0x0ade, DaNike")] [assembly: CLSCompliant(false)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0")] [assembly: AssemblyTitle("MonoMod.ILHelpers")] [assembly: AssemblyCompany("0x0ade, DaNike")] [assembly: AssemblyDescription("Package Description")] [assembly: AssemblyMetadata(".NETFrameworkAssembly", "")] [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: AssemblyVersion("1.1.0.0")] [assembly: TypeForwardedTo(typeof(Unsafe))] namespace System.Runtime.Versioning { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method, AllowMultiple = false, Inherited = false)] internal sealed class NonVersionableAttribute : Attribute { } } namespace System.Runtime.CompilerServices { internal sealed class IsReadOnlyAttribute : Attribute { } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NativeIntegerAttribute : Attribute { public readonly bool[] TransformFlags; public NativeIntegerAttribute() { TransformFlags = new bool[1] { true }; } public NativeIntegerAttribute(bool[] A_0) { TransformFlags = A_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte A_0) { NullableFlags = new byte[1] { A_0 }; } public NullableAttribute(byte[] A_0) { NullableFlags = A_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte A_0) { Flag = A_0; } } } namespace MonoMod { public static class ILHelpers { [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static T TailCallDelegatePtr<T>(IntPtr source) { return ((delegate*<T>)source)(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T TailCallFunc<T>(Func<T> func) { return func(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static ref T ObjectAsRef<T>(object obj) { fixed (object obj2 = obj) { T** ptr = (T**)(&obj2); return ref *(*ptr); } } } } namespace MonoMod.Backports.ILHelpers { public static class UnsafeRaw { [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static T Read<T>(void* source) { return System.Runtime.CompilerServices.Unsafe.Read<T>(source); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static T ReadUnaligned<T>(void* source) { return System.Runtime.CompilerServices.Unsafe.ReadUnaligned<T>(source); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static T ReadUnaligned<T>(ref byte source) { return System.Runtime.CompilerServices.Unsafe.ReadUnaligned<T>(ref source); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static void Write<T>(void* destination, T value) { System.Runtime.CompilerServices.Unsafe.Write(destination, value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static void WriteUnaligned<T>(void* destination, T value) { System.Runtime.CompilerServices.Unsafe.WriteUnaligned(destination, value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static void WriteUnaligned<T>(ref byte destination, T value) { System.Runtime.CompilerServices.Unsafe.WriteUnaligned(ref destination, value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static void Copy<T>(void* destination, ref T source) { System.Runtime.CompilerServices.Unsafe.Write(destination, source); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static void Copy<T>(ref T destination, void* source) { destination = System.Runtime.CompilerServices.Unsafe.Read<T>(source); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static void* AsPointer<T>(ref T value) { return System.Runtime.CompilerServices.Unsafe.AsPointer(ref value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static void SkipInit<T>(out T value) { } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static int SizeOf<T>() { return System.Runtime.CompilerServices.Unsafe.SizeOf<T>(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static void CopyBlock(void* destination, void* source, uint byteCount) { // IL cpblk instruction System.Runtime.CompilerServices.Unsafe.CopyBlock(destination, source, byteCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static void CopyBlock(ref byte destination, ref byte source, uint byteCount) { // IL cpblk instruction System.Runtime.CompilerServices.Unsafe.CopyBlock(ref destination, ref source, byteCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static void CopyBlockUnaligned(void* destination, void* source, uint byteCount) { // IL cpblk instruction System.Runtime.CompilerServices.Unsafe.CopyBlockUnaligned(destination, source, byteCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static void CopyBlockUnaligned(ref byte destination, ref byte source, uint byteCount) { // IL cpblk instruction System.Runtime.CompilerServices.Unsafe.CopyBlockUnaligned(ref destination, ref source, byteCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static void InitBlock(void* startAddress, byte value, uint byteCount) { // IL initblk instruction System.Runtime.CompilerServices.Unsafe.InitBlock(startAddress, value, byteCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static void InitBlock(ref byte startAddress, byte value, uint byteCount) { // IL initblk instruction System.Runtime.CompilerServices.Unsafe.InitBlock(ref startAddress, value, byteCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static void InitBlockUnaligned(void* startAddress, byte value, uint byteCount) { // IL initblk instruction System.Runtime.CompilerServices.Unsafe.InitBlockUnaligned(startAddress, value, byteCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static void InitBlockUnaligned(ref byte startAddress, byte value, uint byteCount) { // IL initblk instruction System.Runtime.CompilerServices.Unsafe.InitBlockUnaligned(ref startAddress, value, byteCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static T As<T>(object o) where T : class { return (T)o; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static ref T AsRef<T>(void* source) { return ref *(T*)source; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static ref T AsRef<T>(in T source) { return ref source; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static ref TTo As<TFrom, TTo>(ref TFrom source) { return ref System.Runtime.CompilerServices.Unsafe.As<TFrom, TTo>(ref source); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static ref T Unbox<T>(object box) where T : struct { return ref (T)box; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static ref T Add<T>(ref T source, int elementOffset) { return ref System.Runtime.CompilerServices.Unsafe.Add(ref source, elementOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static void* Add<T>(void* source, int elementOffset) { return (byte*)source + (nint)elementOffset * (nint)System.Runtime.CompilerServices.Unsafe.SizeOf<T>(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static ref T Add<T>(ref T source, nint elementOffset) { return ref System.Runtime.CompilerServices.Unsafe.Add(ref source, elementOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static ref T Add<T>(ref T source, nuint elementOffset) { return ref System.Runtime.CompilerServices.Unsafe.Add(ref source, elementOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static ref T AddByteOffset<T>(ref T source, nint byteOffset) { return ref System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref source, byteOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static ref T AddByteOffset<T>(ref T source, nuint byteOffset) { return ref System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref source, byteOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static ref T Subtract<T>(ref T source, int elementOffset) { return ref System.Runtime.CompilerServices.Unsafe.Subtract(ref source, elementOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static void* Subtract<T>(void* source, int elementOffset) { return (byte*)source - (nint)elementOffset * (nint)System.Runtime.CompilerServices.Unsafe.SizeOf<T>(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static ref T Subtract<T>(ref T source, nint elementOffset) { return ref System.Runtime.CompilerServices.Unsafe.Subtract(ref source, elementOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static ref T Subtract<T>(ref T source, nuint elementOffset) { return ref System.Runtime.CompilerServices.Unsafe.Subtract(ref source, elementOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static ref T SubtractByteOffset<T>(ref T source, nint byteOffset) { return ref System.Runtime.CompilerServices.Unsafe.SubtractByteOffset(ref source, byteOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static ref T SubtractByteOffset<T>(ref T source, nuint byteOffset) { return ref System.Runtime.CompilerServices.Unsafe.SubtractByteOffset(ref source, byteOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static nint ByteOffset<T>(ref T origin, ref T target) { return System.Runtime.CompilerServices.Unsafe.ByteOffset(target: ref target, origin: ref origin); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static bool AreSame<T>(ref T left, ref T right) { return System.Runtime.CompilerServices.Unsafe.AreSame(ref left, ref right); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static bool IsAddressGreaterThan<T>(ref T left, ref T right) { return System.Runtime.CompilerServices.Unsafe.IsAddressGreaterThan(ref left, ref right); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public static bool IsAddressLessThan<T>(ref T left, ref T right) { return System.Runtime.CompilerServices.Unsafe.IsAddressLessThan(ref left, ref right); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static bool IsNullRef<T>(ref T source) { return System.Runtime.CompilerServices.Unsafe.AsPointer(ref source) == null; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.Versioning.NonVersionable] public unsafe static ref T NullRef<T>() { return ref *(T*)null; } } }
RadioMod\ValheimRadioMod.dll
Decompiled 8 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using SimpleJson; using UnityEngine; using UnityEngine.Networking; using ValheimRadioMod; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ValheimRadioMod")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ValheimRadioMod")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.1.12")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.12.0")] public static class DurationReader { public static float GetDuration(string path) { if (!File.Exists(path)) { return 0f; } string text = Path.GetExtension(path).ToLowerInvariant(); try { return (text == ".wav") ? GetWavDuration(path) : ((!(text == ".mp3")) ? 0f : GetMp3Duration(path)); } catch { return 0f; } } private static float GetWavDuration(string path) { using FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read); using BinaryReader binaryReader = new BinaryReader(fileStream); if (new string(binaryReader.ReadChars(4)) != "RIFF") { return 0f; } binaryReader.ReadInt32(); if (new string(binaryReader.ReadChars(4)) != "WAVE") { return 0f; } short num = 0; short num2 = 0; int num3 = 0; int num4 = 0; while (fileStream.Position < fileStream.Length - 8) { string text = new string(binaryReader.ReadChars(4)); int num5 = binaryReader.ReadInt32(); if (text == "fmt ") { binaryReader.ReadInt16(); num = binaryReader.ReadInt16(); num3 = binaryReader.ReadInt32(); binaryReader.ReadInt32(); binaryReader.ReadInt16(); num2 = binaryReader.ReadInt16(); if (num5 > 16) { binaryReader.ReadBytes(num5 - 16); } } else { if (text == "data") { num4 = num5; break; } binaryReader.ReadBytes(num5); } } if (num3 == 0 || num == 0 || num2 == 0) { return 0f; } return (float)num4 / (float)(num3 * num * (num2 / 8)); } private static float GetMp3Duration(string path) { using FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read); using BinaryReader binaryReader = new BinaryReader(fileStream); if (fileStream.Length > 10 && new string(binaryReader.ReadChars(3)) == "ID3") { binaryReader.ReadBytes(3); int num = ((binaryReader.ReadByte() & 0x7F) << 21) | ((binaryReader.ReadByte() & 0x7F) << 14) | ((binaryReader.ReadByte() & 0x7F) << 7) | (binaryReader.ReadByte() & 0x7F); fileStream.Position = 10 + num; } else { fileStream.Position = 0L; } while (fileStream.Position < fileStream.Length - 4) { if (binaryReader.ReadByte() == byte.MaxValue && (binaryReader.ReadByte() & 0xE0) == 224) { fileStream.Position -= 2L; int bitrate = GetBitrate(binaryReader.ReadBytes(4)); if (bitrate > 0) { return (float)((fileStream.Length - fileStream.Position + 4) * 8) / (float)(bitrate * 1000); } } } return 0f; } private static int GetBitrate(byte[] h) { int num = (h[2] >> 4) & 0xF; int[] array = new int[16] { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 }; if (num >= array.Length) { return 0; } return array[num]; } } public class RadioLoadingUI : MonoBehaviour { private void OnGUI() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)AudioManager.Instance == (Object)null) && AudioManager.Instance.IsLoading) { AudioManager instance = AudioManager.Instance; float num = ((instance.TotalStations > 0) ? ((float)instance.LoadedStations / (float)instance.TotalStations) : 0f); float num2 = 520f; float num3 = 200f; float num4 = ((float)Screen.width - num2) / 2f; float num5 = ((float)Screen.height - num3) / 2f - (float)Screen.height * 0.05f; Color color = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.75f); GUI.Box(new Rect(num4 - 10f, num5 - 10f, num2 + 20f, num3 + 20f), ""); GUI.color = color; GUILayout.BeginArea(new Rect(num4, num5, num2, num3)); GUILayout.Space(12f); GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 14 }; GUIStyle val2 = new GUIStyle(val) { fontSize = 22, fontStyle = (FontStyle)1 }; GUILayout.Label("Valheim Radio Mod", val2, Array.Empty<GUILayoutOption>()); GUILayout.Space(8f); GUILayout.Label(Localization.instance.Localize("$radio_loading_wait"), val, Array.Empty<GUILayoutOption>()); GUILayout.Label(Localization.instance.Localize("$radio_loading_stations"), val, Array.Empty<GUILayoutOption>()); Rect rect = GUILayoutUtility.GetRect(num2 - 40f, 22f); ((Rect)(ref rect)).x = ((Rect)(ref rect)).x + 10f; GUI.Box(rect, ""); GUI.Box(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width * num, ((Rect)(ref rect)).height), ""); GUILayout.Space(6f); GUILayout.Label(string.Format(Localization.instance.Localize("$radio_loading_station"), instance.LoadedStations + 1, instance.TotalStations, instance.CurrentStationName), val, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format(Localization.instance.Localize("$radio_loading_track"), instance.CurrentTrackIndex, instance.CurrentStationTracks, instance.CurrentTrackName), val, Array.Empty<GUILayoutOption>()); GUILayout.EndArea(); } } } namespace ValheimRadioMod; internal class AudioManager : MonoBehaviour { private Dictionary<string, List<string>> stationFiles = new Dictionary<string, List<string>>(); private Dictionary<string, List<AudioClip>> stationClips = new Dictionary<string, List<AudioClip>>(); private Dictionary<string, List<float>> stationDurations = new Dictionary<string, List<float>>(); private Dictionary<string, float> stationTotalDuration = new Dictionary<string, float>(); public static AudioManager Instance { get; private set; } public IReadOnlyCollection<string> StationNames => stationFiles.Keys; public int TotalStations { get; private set; } public int LoadedStations { get; private set; } public int CurrentStationTracks { get; private set; } public int CurrentTrackIndex { get; private set; } public string CurrentStationName { get; private set; } = ""; public string CurrentTrackName { get; private set; } = ""; public bool IsLoading { get; private set; } private void Awake() { if ((Object)(object)Instance != (Object)null) { Object.Destroy((Object)(object)this); } else { Instance = this; } } public void LoadStations(string modPath) { string text = Path.Combine(modPath, "Audio"); if (!Directory.Exists(text)) { Logger.LogWarning((object)("Audio folder not found: " + text)); return; } string[] directories = Directory.GetDirectories(text); foreach (string path in directories) { string fileName = Path.GetFileName(path); List<string> list = (from f in Directory.GetFiles(path).Where(delegate(string f) { switch (Path.GetExtension(f).ToLowerInvariant()) { case ".mp3": case ".ogg": case ".wav": case ".m4a": return true; default: return false; } }) orderby ExtractOrder(Path.GetFileNameWithoutExtension(f)) select f).ThenBy<string, string>((string f) => Path.GetFileName(f), StringComparer.OrdinalIgnoreCase).ToList(); if (list.Count != 0) { stationFiles[fileName] = list; stationClips[fileName] = new List<AudioClip>(); stationDurations[fileName] = new List<float>(); } } ((MonoBehaviour)this).StartCoroutine(LoadAllTracksDelayed()); } private int ExtractOrder(string name) { Match match = Regex.Match(name, "^(\\d+)"); if (!match.Success) { return int.MaxValue; } return int.Parse(match.Value); } private IEnumerator LoadAllTracksDelayed() { yield return (object)new WaitForSeconds(10f); Logger.LogInfo((object)"Starting full station load..."); IsLoading = true; TotalStations = stationFiles.Count; LoadedStations = 0; using (Dictionary<string, List<string>>.KeyCollection.Enumerator enumerator = stationFiles.Keys.GetEnumerator()) { while (enumerator.MoveNext()) { string station = (CurrentStationName = enumerator.Current); yield return ((MonoBehaviour)this).StartCoroutine(LoadEntireStation(station)); LoadedStations++; yield return (object)new WaitForSeconds(0.1f); } } IsLoading = false; Logger.LogInfo((object)"All stations loaded."); } private IEnumerator LoadEntireStation(string station) { List<string> files = stationFiles[station]; float total = 0f; CurrentStationTracks = files.Count; for (int i = 0; i < files.Count; i++) { CurrentTrackIndex = i + 1; CurrentTrackName = Path.GetFileNameWithoutExtension(files[i]); string path = files[i]; string text = "file://" + path.Replace("\\", "/"); AudioType val = (AudioType)0; switch (Path.GetExtension(path).ToLowerInvariant()) { case ".mp3": val = (AudioType)13; break; case ".ogg": val = (AudioType)14; break; case ".wav": val = (AudioType)20; break; } UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(text, val); try { yield return www.SendWebRequest(); if ((int)www.result == 1) { AudioClip content = DownloadHandlerAudioClip.GetContent(www); ((Object)content).name = Path.GetFileNameWithoutExtension(path); stationClips[station].Add(content); stationDurations[station].Add(content.length); total += content.length; } else { Logger.LogWarning((object)("Failed to load " + path)); stationClips[station].Add(null); stationDurations[station].Add(0f); } if (i % 2 == 0) { yield return null; } } finally { ((IDisposable)www)?.Dispose(); } } stationTotalDuration[station] = total; Logger.LogInfo((object)$"Station '{station}' loaded: {files.Count} tracks, total {total:F1}s"); } public (AudioClip clip, float position) GetCurrentPlayback(string station) { if (!stationClips.TryGetValue(station, out var value) || value.Count == 0) { return (clip: null, position: 0f); } if (!stationTotalDuration.TryGetValue(station, out var value2) || value2 <= 0f) { return (clip: null, position: 0f); } float num = (float)((((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble) % (double)value2); float num2 = 0f; int index = 0; float num3 = 0f; List<float> list = stationDurations[station]; for (int i = 0; i < list.Count; i++) { float num4 = list[i]; if (!(num4 <= 0f)) { if (num < num2 + num4) { index = i; num3 = num - num2; break; } num2 += num4; } } AudioClip val = value[index]; if ((Object)(object)val == (Object)null) { return (clip: null, position: 0f); } return (clip: val, position: Mathf.Clamp(num3, 0f, val.length - 0.05f)); } } public static class MouseScrollPatch { public static float LastScrollDelta { get; set; } public static void ApplyPatch(Harmony harmony) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown try { Type type = AccessTools.TypeByName("ZInput"); if (!(type == null)) { MethodInfo methodInfo = AccessTools.Method(type, "GetMouseScrollWheel", (Type[])null, (Type[])null); if (!(methodInfo == null)) { MethodInfo methodInfo2 = AccessTools.Method(typeof(MouseScrollPatch), "Prefix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Logger.LogInfo((object)"Mouse scroll patch applied"); } } } catch (Exception ex) { Logger.LogError((object)("Failed to patch mouse scroll: " + ex.Message)); } } public static bool Prefix(ref float __result) { LastScrollDelta = Input.GetAxis("Mouse ScrollWheel"); if (RadioBehaviour.IsAnyHovered) { __result = 0f; return false; } return true; } } public class RadioBehaviour : MonoBehaviour, Hoverable, Interactable, TextReceiver { private static readonly HashSet<RadioBehaviour> AllRadios = new HashSet<RadioBehaviour>(); private static readonly HashSet<RadioBehaviour> HoveredRadios = new HashSet<RadioBehaviour>(); private float hoverEndTime; public string CurrentStation = ""; public bool IsOn = true; public float Volume = 0.5f; public string Group = ""; private AudioSource audioSource; private bool forceClipRefresh; private ZNetView znetView; private float ePressTime = -1f; private const float LongPressDuration = 0.6f; public static bool IsAnyHovered => HoveredRadios.Count > 0; private void Awake() { audioSource = ((Component)this).gameObject.AddComponent<AudioSource>(); audioSource.spatialBlend = 1f; audioSource.rolloffMode = (AudioRolloffMode)1; audioSource.maxDistance = 30f; audioSource.loop = false; audioSource.volume = Volume; znetView = ((Component)this).GetComponent<ZNetView>(); AllRadios.Add(this); Shader val = Shader.Find("Custom/Piece"); if (!((Object)(object)val != (Object)null)) { return; } Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { Material[] materials = val2.materials; for (int j = 0; j < materials.Length; j++) { if ((Object)(object)materials[j] != (Object)null) { materials[j].shader = val; } } val2.materials = materials; } } private void Start() { LoadFromZDO(); if (!string.IsNullOrEmpty(CurrentStation) || !((Object)(object)AudioManager.Instance != (Object)null) || AudioManager.Instance.StationNames.Count <= 0) { return; } using (IEnumerator<string> enumerator = AudioManager.Instance.StationNames.GetEnumerator()) { if (enumerator.MoveNext()) { string current = enumerator.Current; CurrentStation = current; } } SaveToZDO(); } private void OnDestroy() { AllRadios.Remove(this); HoveredRadios.Remove(this); } private void LoadFromZDO() { if (!((Object)(object)znetView == (Object)null) && znetView.IsValid()) { CurrentStation = znetView.GetZDO().GetString("station", CurrentStation); IsOn = znetView.GetZDO().GetBool("on", IsOn); Volume = znetView.GetZDO().GetFloat("volume", Volume); Group = znetView.GetZDO().GetString("group", Group); } } private void SaveToZDO() { if (!((Object)(object)znetView == (Object)null) && znetView.IsValid() && znetView.IsOwner()) { znetView.GetZDO().Set("station", CurrentStation); znetView.GetZDO().Set("on", IsOn); znetView.GetZDO().Set("volume", Volume); znetView.GetZDO().Set("group", Group); } } private void Update() { if (Time.time >= hoverEndTime) { HoveredRadios.Remove(this); } audioSource.mute = Time.timeScale == 0f; if (Time.time < hoverEndTime && !TextInput.IsVisible()) { if (ZInput.GetKeyDown((KeyCode)101, true)) { ePressTime = Time.time; } if (ZInput.GetKey((KeyCode)101, true) && ePressTime > 0f && Time.time - ePressTime >= 0.6f) { CycleStation(); ePressTime = -1f; } if (ZInput.GetKeyUp((KeyCode)101, true)) { if (ePressTime > 0f && Time.time - ePressTime < 0.6f) { SetOn(!IsOn); } ePressTime = -1f; } if (ZInput.GetKeyDown((KeyCode)101, true) && (ZInput.GetKey((KeyCode)304, true) || ZInput.GetKey((KeyCode)303, true))) { OpenGroupRename(); ePressTime = -1f; } } if ((Object)(object)znetView != (Object)null && znetView.IsValid()) { LoadFromZDO(); } if (!IsOn || (Object)(object)AudioManager.Instance == (Object)null) { if (audioSource.isPlaying) { audioSource.Stop(); } return; } var (val, num) = AudioManager.Instance.GetCurrentPlayback(CurrentStation); if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)audioSource.clip != (Object)(object)val || forceClipRefresh) { audioSource.clip = val; audioSource.time = num; audioSource.Play(); forceClipRefresh = false; } else if (Mathf.Abs(audioSource.time - num) > 0.4f) { audioSource.time = num; } audioSource.volume = Volume; if (Time.time < hoverEndTime) { float lastScrollDelta = MouseScrollPatch.LastScrollDelta; if (lastScrollDelta != 0f) { SetVolume(Volume + lastScrollDelta * 0.5f); MouseScrollPatch.LastScrollDelta = 0f; } } } private void OpenGroupRename() { TextInput.instance.RequestText((TextReceiver)(object)this, "$radio_group", 20); } public string GetText() { return Group ?? ""; } public void SetText(string text) { SetGroup(text.Trim()); } public string GetHoverText() { hoverEndTime = Time.time + 0.2f; HoveredRadios.Add(this); string value = (IsOn ? Localization.instance.Localize("$radio_on") : Localization.instance.Localize("$radio_off")); string value2 = (string.IsNullOrEmpty(Group) ? Localization.instance.Localize("$radio_no_group") : Group); string value3 = ""; if (IsOn && (Object)(object)AudioManager.Instance != (Object)null && !string.IsNullOrEmpty(CurrentStation)) { AudioClip item = AudioManager.Instance.GetCurrentPlayback(CurrentStation).clip; if ((Object)(object)item != (Object)null) { string value4 = CleanTrackName(((Object)item).name); value3 = $"\n<color=#FFD700>{CurrentStation}</color>\n<color=#AAAAAA>{value4}</color>"; } } return $"<size=16><b>{Localization.instance.Localize("$radio_name")}</b></size> ({value}){value3}\n<color=#888888>────────────────</color>\n[<color=yellow><b>E</b></color>] {Localization.instance.Localize("$radio_toggle")}\n[<color=yellow><b>{Localization.instance.Localize("$radio_e_hold")}</b></color>] {Localization.instance.Localize("$radio_next_station")}\n[<color=yellow><b>Shift + E</b></color>] {Localization.instance.Localize("$radio_group")}: {value2}\n[<color=yellow><b>{Localization.instance.Localize("$radio_mouse_wheel")}</b></color>] {Localization.instance.Localize("$radio_volume")} ({Volume:P0})"; } public string GetHoverName() { return "Radio"; } public float GetHoverOffset() { return 1.5f; } public bool Interact(Humanoid user, bool hold, bool alt) { return false; } public bool UseItem(Humanoid user, ItemData item) { return false; } private void CycleStation() { if (!((Object)(object)AudioManager.Instance == (Object)null) && AudioManager.Instance.StationNames.Count != 0) { List<string> list = new List<string>(AudioManager.Instance.StationNames); int num = list.IndexOf(CurrentStation); string station = list[(num + 1) % list.Count]; SetStation(station); } } public void SetOn(bool value) { IsOn = value; forceClipRefresh = true; SaveToZDO(); SyncGroup(); } public void SetVolume(float value) { Volume = Mathf.Clamp01(value); SaveToZDO(); SyncGroup(); } public void SetStation(string station) { CurrentStation = station; forceClipRefresh = true; SaveToZDO(); SyncGroup(); } public void SetGroup(string group) { Group = group ?? ""; SaveToZDO(); if (string.IsNullOrEmpty(Group)) { return; } foreach (RadioBehaviour allRadio in AllRadios) { if (!((Object)(object)allRadio == (Object)(object)this) && !(allRadio.Group != Group)) { IsOn = allRadio.IsOn; Volume = allRadio.Volume; CurrentStation = allRadio.CurrentStation; forceClipRefresh = true; SaveToZDO(); break; } } } private void SyncGroup() { if (string.IsNullOrEmpty(Group)) { return; } foreach (RadioBehaviour allRadio in AllRadios) { if (!((Object)(object)allRadio == (Object)(object)this) && !(allRadio.Group != Group)) { allRadio.IsOn = IsOn; allRadio.Volume = Volume; allRadio.CurrentStation = CurrentStation; allRadio.forceClipRefresh = true; allRadio.SaveToZDO(); } } } private string CleanTrackName(string name) { if (string.IsNullOrEmpty(name)) { return name; } Match match = Regex.Match(name, "^\\d+[\\s\\.\\-_]+"); if (!match.Success) { return name; } return name.Substring(match.Length).Trim(); } } [BepInPlugin("com.schpipo.ValheimRadioMod", "ValheimRadioMod", "0.1.12")] [BepInDependency(/*Could not decode attribute arguments.*/)] internal class ValheimRadioMod : BaseUnityPlugin { [HarmonyPatch(typeof(Player), "StartEmote")] private static class BlockEmoteOnRadio { private static bool Prefix() { return !RadioBehaviour.IsAnyHovered; } } public const string PluginGUID = "com.schpipo.ValheimRadioMod"; public const string PluginName = "ValheimRadioMod"; public const string PluginVersion = "0.1.12"; private bool firstTracksStarted; private void Awake() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown Logger.LogInfo((object)"ValheimRadioMod has landed"); Harmony val = new Harmony("com.schpipo.ValheimRadioMod"); MouseScrollPatch.ApplyPatch(val); val.PatchAll(); LoadLocalization(); GameObject val2 = new GameObject("RadioAudioManager"); val2.AddComponent<AudioManager>(); Object.DontDestroyOnLoad((Object)val2); string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); AudioManager.Instance.LoadStations(directoryName); AddRadioPiece(); GameObject val3 = new GameObject("RadioLoadingUI"); val3.AddComponent<RadioLoadingUI>(); Object.DontDestroyOnLoad((Object)val3); } private void LoadLocalization() { string path = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "Localization.json"); if (!File.Exists(path)) { Logger.LogWarning((object)"Localization.json not found"); return; } try { Dictionary<string, Dictionary<string, string>> dictionary = SimpleJson.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(File.ReadAllText(path)); CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); foreach (KeyValuePair<string, Dictionary<string, string>> item in dictionary) { string key = item.Key; localization.AddTranslation(ref key, item.Value); Logger.LogInfo((object)("Loaded localization for " + item.Key)); } } catch (Exception ex) { Logger.LogError((object)("Failed to load Localization.json: " + ex.Message)); } } private void AddRadioPiece() { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown string? directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); GameObject val = AssetUtils.LoadAssetBundle(Path.Combine(directoryName, "radio")).LoadAsset<GameObject>("radio"); if ((Object)(object)val.GetComponent<ZNetView>() == (Object)null) { val.AddComponent<ZNetView>().m_persistent = true; } val.AddComponent<RadioBehaviour>(); Piece obj = val.AddComponent<Piece>(); obj.m_name = "Radio"; obj.m_description = "A radio that plays music."; obj.m_canBeRemoved = true; obj.m_enabled = true; Sprite icon = AssetUtils.LoadSpriteFromFile(Path.Combine(directoryName, "icon_build.png")); PieceConfig val2 = new PieceConfig(); val2.Name = "Radio"; val2.Description = "A radio that plays music."; val2.PieceTable = PieceTables.Hammer; val2.Category = "Misc"; val2.Usage = new string[1] { PieceUsages.Furniture }; val2.Icon = icon; PieceConfig val3 = val2; RequirementConfig val4 = new RequirementConfig("Wood", 5, 0, true); val4.Recover = true; val3.AddRequirement(val4); PieceManager.Instance.AddPiece(new CustomPiece(val, false, val3)); } private void Update() { if (!firstTracksStarted && (Object)(object)ZNet.instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null) { firstTracksStarted = true; } } }