using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using JetBrains.Annotations; #pragma warning disable 169 namespace Robust.Shared.Utility { /// /// Fixed size array stack allocation helpers. /// /// /// /// This helper class can be used to work around the limitation that stackalloc /// cannot be used with ref types. /// /// /// To use, call it like so: /// /// var span = FixedArray.Alloc32<object>(out _); /// /// There is an out parameter that you should probably always discard (as shown in the example). /// This is so that stack space is properly allocated in your stack frame. /// /// /// Do NOT under ANY CIRCUMSTANCE return the span given up the stack in any way. /// You will break the GC and stack and (worst of all) I will shed you. /// /// /// This class cannot be used with variable size allocations. /// Just allocate a we'll-never-need-more bound like 128 and slim it down. /// /// [PublicAPI] [SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeNotEvident")] internal static class FixedArray { public static Span Alloc2(out FixedArray2 discard) { discard = new(); return discard.AsSpan; } public static Span Alloc4(out FixedArray4 discard) { discard = new(); return discard.AsSpan; } public static Span Alloc8(out FixedArray8 discard) { discard = new(); return discard.AsSpan; } public static Span Alloc16(out FixedArray16 discard) { discard = new(); return discard.AsSpan; } public static Span Alloc32(out FixedArray32 discard) { discard = new(); return discard.AsSpan; } public static Span Alloc64(out FixedArray64 discard) { discard = new(); return discard.AsSpan; } public static Span Alloc128(out FixedArray128 discard) { discard = new(); return discard.AsSpan; } } internal struct FixedArray2 { private T _00; private T _01; public Span AsSpan => MemoryMarshal.CreateSpan(ref _00, 2); } internal struct FixedArray4 { private T _00; private T _01; private T _02; private T _03; public Span AsSpan => MemoryMarshal.CreateSpan(ref _00, 4); } internal struct FixedArray8 { private T _00; private T _01; private T _02; private T _03; private T _04; private T _05; private T _06; private T _07; public Span AsSpan => MemoryMarshal.CreateSpan(ref _00, 8); } internal struct FixedArray16 { private T _00; private T _01; private T _02; private T _03; private T _04; private T _05; private T _06; private T _07; private T _08; private T _09; private T _10; private T _11; private T _12; private T _13; private T _14; private T _15; public Span AsSpan => MemoryMarshal.CreateSpan(ref _00, 16); } internal struct FixedArray32 { private T _00; private T _01; private T _02; private T _03; private T _04; private T _05; private T _06; private T _07; private T _08; private T _09; private T _10; private T _11; private T _12; private T _13; private T _14; private T _15; private T _16; private T _17; private T _18; private T _19; private T _20; private T _21; private T _22; private T _23; private T _24; private T _25; private T _26; private T _27; private T _28; private T _29; private T _30; private T _31; public Span AsSpan => MemoryMarshal.CreateSpan(ref _00, 32); } internal struct FixedArray64 { private T _00; private T _01; private T _02; private T _03; private T _04; private T _05; private T _06; private T _07; private T _08; private T _09; private T _10; private T _11; private T _12; private T _13; private T _14; private T _15; private T _16; private T _17; private T _18; private T _19; private T _20; private T _21; private T _22; private T _23; private T _24; private T _25; private T _26; private T _27; private T _28; private T _29; private T _30; private T _31; private T _32; private T _33; private T _34; private T _35; private T _36; private T _37; private T _38; private T _39; private T _40; private T _41; private T _42; private T _43; private T _44; private T _45; private T _46; private T _47; private T _48; private T _49; private T _50; private T _51; private T _52; private T _53; private T _54; private T _55; private T _56; private T _57; private T _58; private T _59; private T _60; private T _61; private T _62; private T _63; public Span AsSpan => MemoryMarshal.CreateSpan(ref _00, 64); } internal struct FixedArray128 { private T _00; private T _01; private T _02; private T _03; private T _04; private T _05; private T _06; private T _07; private T _08; private T _09; private T _10; private T _11; private T _12; private T _13; private T _14; private T _15; private T _16; private T _17; private T _18; private T _19; private T _20; private T _21; private T _22; private T _23; private T _24; private T _25; private T _26; private T _27; private T _28; private T _29; private T _30; private T _31; private T _32; private T _33; private T _34; private T _35; private T _36; private T _37; private T _38; private T _39; private T _40; private T _41; private T _42; private T _43; private T _44; private T _45; private T _46; private T _47; private T _48; private T _49; private T _50; private T _51; private T _52; private T _53; private T _54; private T _55; private T _56; private T _57; private T _58; private T _59; private T _60; private T _61; private T _62; private T _63; private T _64; private T _65; private T _66; private T _67; private T _68; private T _69; private T _70; private T _71; private T _72; private T _73; private T _74; private T _75; private T _76; private T _77; private T _78; private T _79; private T _80; private T _81; private T _82; private T _83; private T _84; private T _85; private T _86; private T _87; private T _88; private T _89; private T _90; private T _91; private T _92; private T _93; private T _94; private T _95; private T _96; private T _97; private T _98; private T _99; private T _100; private T _101; private T _102; private T _103; private T _104; private T _105; private T _106; private T _107; private T _108; private T _109; private T _110; private T _111; private T _112; private T _113; private T _114; private T _115; private T _116; private T _117; private T _118; private T _119; private T _120; private T _121; private T _122; private T _123; private T _124; private T _125; private T _126; private T _127; public Span AsSpan => MemoryMarshal.CreateSpan(ref _00, 128); } }