private void OnFieldChanged(object?sender, FieldChangedEventArgs eventArgs)
            {
                var fieldIdentifier = eventArgs.FieldIdentifier;

                if (TryGetValidatableProperty(fieldIdentifier, out var propertyInfo))
                {
                    var propertyValue     = propertyInfo.GetValue(fieldIdentifier.Model);
                    var validationContext = new ValidationContext(fieldIdentifier.Model)
                    {
                        MemberName = propertyInfo.Name
                    };
                    var results = new List <ValidationResult>();

                    Validator.TryValidateProperty(propertyValue, validationContext, results);
                    _messages.Clear(fieldIdentifier);
                    foreach (var result in CollectionsMarshal.AsSpan(results))
                    {
                        _messages.Add(fieldIdentifier, result.ErrorMessage !);
                    }

                    // We have to notify even if there were no messages before and are still no messages now,
                    // because the "state" that changed might be the completion of some async validation task
                    _editContext.NotifyValidationStateChanged();
                }
            }
예제 #2
0
    /// <summary>
    /// Calls the <see cref="ITagHelperComponent.ProcessAsync"/> method on <see cref="ITagHelper"/>s.
    /// </summary>
    /// <param name="executionContext">Contains information associated with running <see cref="ITagHelper"/>s.
    /// </param>
    /// <returns>Resulting <see cref="TagHelperOutput"/> from processing all of the
    /// <paramref name="executionContext"/>'s <see cref="ITagHelper"/>s.</returns>
    public Task RunAsync(TagHelperExecutionContext executionContext)
    {
        if (executionContext == null)
        {
            throw new ArgumentNullException(nameof(executionContext));
        }

        var tagHelperContext = executionContext.Context;
        var tagHelpers       = CollectionsMarshal.AsSpan(executionContext.TagHelperList);

        tagHelpers.Sort(default(SortTagHelpers));

        foreach (var tagHelper in tagHelpers)
        {
            tagHelper.Init(tagHelperContext);
        }

        var tagHelperOutput = executionContext.Output;

        for (var i = 0; i < tagHelpers.Length; i++)
        {
            var task = tagHelpers[i].ProcessAsync(tagHelperContext, tagHelperOutput);
            if (!task.IsCompletedSuccessfully)
            {
                return(Awaited(task, executionContext, i + 1, tagHelpers.Length));
            }
        }

        return(Task.CompletedTask);
예제 #3
0
        private List <T> ReadPrimitiveList <T>(int count) where T : unmanaged
        {
            var values = new List <T>(count);

            Read(MemoryMarshal.AsBytes(CollectionsMarshal.AsSpan(values)));
            return(values);
        }
예제 #4
0
    public void SortByPrimaryFitness()
    {
        const double champFitness = 100.0;

        var           genomeComparerDescending = new GenomeComparerDescending(PrimaryFitnessInfoComparer.Singleton);
        IRandomSource rng = RandomDefaults.CreateRandomSource(0);

        // Run the inner test multiple times, with a different champ genome count each time.
        for (int champGenomeCount = 1; champGenomeCount <= 10; champGenomeCount++)
        {
            Species <double> species = CreateTestSpecies(10);

            AssignGenomeFitnessScores(species, champGenomeCount, champFitness, rng);
            SortUtils.SortUnstable(
                CollectionsMarshal.AsSpan(species.GenomeList),
                genomeComparerDescending,
                rng);

            // Assert that the champ genomes have been sorted to the head of the genome list.
            int idx = 0;
            for (; idx < champGenomeCount; idx++)
            {
                Assert.Equal(champFitness, species.GenomeList[idx].FitnessInfo.PrimaryFitness);
            }

            // Assert that all other genomes have a fitness less than the champ fitness.
            for (; idx < species.GenomeList.Count; idx++)
            {
                Assert.True(species.GenomeList[idx].FitnessInfo.PrimaryFitness < champFitness);
            }
        }
    }
예제 #5
0
        static void Pack(PackOptions options)
        {
            var data             = new List <byte>(150 * 1000 * 1000);
            var files            = Directory.GetFiles(options.SourceFolder).ToDictionary(Path.GetFileName, StringComparer.OrdinalIgnoreCase);
            var originalJsonFile = JsonDatFile.FromFile(options.SourceJson);
            var jsonFile         = new JsonDatFile();

            Directory.CreateDirectory(Path.GetDirectoryName(options.JsonPath));
            Directory.CreateDirectory(Path.GetDirectoryName(options.DatPath));

            foreach (var origFile in originalJsonFile.Files)
            {
                if (files.TryGetValue(origFile.Name, out var file))
                {
                    var fileBytes     = File.ReadAllBytes(file);
                    int currentOffset = data.Count;
                    var fileEntry     = new JsonFileEntry(Path.GetFileName(file), fileBytes.Length, currentOffset);

                    data.AddRange(fileBytes);
                    jsonFile.Files.Add(fileEntry);
                    data.AddPadding(2048);
                }
            }

            // Save (Note: Using FileStream to avoid copying large array)
            File.WriteAllText(options.JsonPath, jsonFile.ToFile());
            using var fileStream = new FileStream(options.DatPath, FileMode.Create);
            fileStream.Write(CollectionsMarshal.AsSpan(data));

            Console.WriteLine($"JSON file for injection written to: {options.JsonPath}");
            Console.WriteLine($"New DAT file written to: {options.DatPath}");
        }
예제 #6
0
        private unsafe void SetUp()
        {
            VAO = new("Mesh VAO");
            VBO = new("Mesh VBO");
            EBO = new("Mesh EBO");

            VAO.Bind();
            VBO.Bind(BufferTarget.ArrayBuffer);

            // Buffer the vertex data into the VBO.
            var verarr = CollectionsMarshal.AsSpan(Vertices);

            GL.BufferData(BufferTarget.ArrayBuffer, verarr.Length * sizeof(Vertex), ref verarr[0], BufferUsageHint.StaticDraw);

            EBO.Bind(BufferTarget.ElementArrayBuffer);

            // Buffer the element array into the EBO.
            var indarr = CollectionsMarshal.AsSpan(Indices);

            GL.BufferData(BufferTarget.ElementArrayBuffer, indarr.Length * sizeof(uint), ref indarr[0], BufferUsageHint.StaticDraw);

            SetupPointers();

            GL.BindVertexArray(0);
        }
예제 #7
0
        static void Main()
        {
            ArraySegments.Test4();
            Test();

            using IMemoryOwner <char> owner = MemoryPool <char> .Shared.Rent();

            Console.Write("Enter a number: ");
            try
            {
                int           value  = int.Parse(Console.ReadLine());
                Memory <char> memory = owner.Memory;
                WriteInt32ToBuffer(value, memory);
                DisplayBufferToConsole(memory.Slice(0, value.ToString().Length));
                var list     = new List <int>();
                var listSpan = CollectionsMarshal.AsSpan(list);
            }
            catch (FormatException)
            {
                Console.WriteLine("You did not enter a valid number.");
            }
            catch (OverflowException)
            {
                Console.WriteLine($"You entered a number less than {int.MinValue:N0} or greater than {int.MaxValue:N0}.");
            }
        }
예제 #8
0
        public void ConstantSizeCollection()
        {
            var longVal = 0x12345678ABCDEF10L;

            Assert.Equal(longVal, MemoryMarshal.Read <long>(CollectionsMarshal.AsSpan(NativeExportsNE.Collections.Stateless.GetLongBytes(longVal))));
            Assert.Equal(longVal, MemoryMarshal.Read <long>(CollectionsMarshal.AsSpan(NativeExportsNE.Collections.Stateful.GetLongBytes(longVal))));
        }
예제 #9
0
        public unsafe void NullListAsSpanClass()
        {
            List <object> list = null;
            Span <object> span = CollectionsMarshal.AsSpan(list);

            Assert.Equal(0, span.Length);
        }
예제 #10
0
        internal static Span <byte> AssembleCall32(CallDescriptor <int> callDescriptor)
        {
            var shellcode = new List <byte>();

            foreach (var argument in callDescriptor.Arguments.Reverse())
            {
                switch (argument)
                {
                case >= sbyte.MinValue and <= sbyte.MaxValue:
                {
                    // push argument

                    shellcode.AddRange(new byte[] { 0x6A, unchecked ((byte)argument) });

                    break;
                }

                default:
                {
                    // push argument

                    shellcode.Add(0x68);

                    shellcode.AddRange(BitConverter.GetBytes(argument));

                    break;
                }
                }
            }

            // mov eax, Address

            shellcode.Add(0xB8);

            shellcode.AddRange(BitConverter.GetBytes(callDescriptor.Address.ToInt32()));

            // call eax

            shellcode.AddRange(new byte[] { 0xFF, 0xD0 });

            if (callDescriptor.ReturnAddress != IntPtr.Zero)
            {
                // mov ReturnAddress, eax

                shellcode.Add(0xA3);

                shellcode.AddRange(BitConverter.GetBytes(callDescriptor.ReturnAddress.ToInt32()));
            }

            // xor eax, eax

            shellcode.AddRange(new byte[] { 0x33, 0xC0 });

            // ret

            shellcode.Add(0xC3);

            return(CollectionsMarshal.AsSpan(shellcode));
        }
예제 #11
0
        public static void ComparerImplementations_Dictionary_WithWellKnownStringComparers()
        {
            Type nonRandomizedOrdinalComparerType           = typeof(object).Assembly.GetType("System.Collections.Generic.NonRandomizedStringEqualityComparer+OrdinalComparer", throwOnError: true);
            Type nonRandomizedOrdinalIgnoreCaseComparerType = typeof(object).Assembly.GetType("System.Collections.Generic.NonRandomizedStringEqualityComparer+OrdinalIgnoreCaseComparer", throwOnError: true);
            Type randomizedOrdinalComparerType           = typeof(object).Assembly.GetType("System.Collections.Generic.RandomizedStringEqualityComparer+OrdinalComparer", throwOnError: true);
            Type randomizedOrdinalIgnoreCaseComparerType = typeof(object).Assembly.GetType("System.Collections.Generic.RandomizedStringEqualityComparer+OrdinalIgnoreCaseComparer", throwOnError: true);

            // null comparer

            RunDictionaryTest(
                equalityComparer: null,
                expectedInternalComparerTypeBeforeCollisionThreshold: nonRandomizedOrdinalComparerType,
                expectedPublicComparerBeforeCollisionThreshold: EqualityComparer <string> .Default,
                expectedInternalComparerTypeAfterCollisionThreshold: randomizedOrdinalComparerType);

            // EqualityComparer<string>.Default comparer

            RunDictionaryTest(
                equalityComparer: EqualityComparer <string> .Default,
                expectedInternalComparerTypeBeforeCollisionThreshold: nonRandomizedOrdinalComparerType,
                expectedPublicComparerBeforeCollisionThreshold: EqualityComparer <string> .Default,
                expectedInternalComparerTypeAfterCollisionThreshold: randomizedOrdinalComparerType);

            // Ordinal comparer

            RunDictionaryTest(
                equalityComparer: StringComparer.Ordinal,
                expectedInternalComparerTypeBeforeCollisionThreshold: nonRandomizedOrdinalComparerType,
                expectedPublicComparerBeforeCollisionThreshold: StringComparer.Ordinal,
                expectedInternalComparerTypeAfterCollisionThreshold: randomizedOrdinalComparerType);

            // OrdinalIgnoreCase comparer

            RunDictionaryTest(
                equalityComparer: StringComparer.OrdinalIgnoreCase,
                expectedInternalComparerTypeBeforeCollisionThreshold: nonRandomizedOrdinalIgnoreCaseComparerType,
                expectedPublicComparerBeforeCollisionThreshold: StringComparer.OrdinalIgnoreCase,
                expectedInternalComparerTypeAfterCollisionThreshold: randomizedOrdinalIgnoreCaseComparerType);

            // linguistic comparer (not optimized)

            RunDictionaryTest(
                equalityComparer: StringComparer.InvariantCulture,
                expectedInternalComparerTypeBeforeCollisionThreshold: StringComparer.InvariantCulture.GetType(),
                expectedPublicComparerBeforeCollisionThreshold: StringComparer.InvariantCulture,
                expectedInternalComparerTypeAfterCollisionThreshold: StringComparer.InvariantCulture.GetType());

            // CollectionsMarshal.GetValueRefOrAddDefault

            RunCollectionTestCommon(
                () => new Dictionary <string, object>(StringComparer.Ordinal),
                (dictionary, key) => CollectionsMarshal.GetValueRefOrAddDefault(dictionary, key, out _) = null,
                (dictionary, key) => dictionary.ContainsKey(key),
                dictionary => dictionary.Comparer,
                expectedInternalComparerTypeBeforeCollisionThreshold: nonRandomizedOrdinalComparerType,
                expectedPublicComparerBeforeCollisionThreshold: StringComparer.Ordinal,
                expectedInternalComparerTypeAfterCollisionThreshold: randomizedOrdinalComparerType);
        public int List_Span()
        {
            var sum = 0;

            foreach (var item in CollectionsMarshal.AsSpan(list))
            {
                sum += item;
            }
            return(sum);
        }
예제 #13
0
        public unsafe void NullListAsSpanValueType()
        {
            List <int> list = null;
            Span <int> span = CollectionsMarshal.AsSpan(list);

            Assert.Equal(0, span.Length);

            fixed(int *pSpan = span)
            {
                Assert.True(pSpan == null);
            }
        }
예제 #14
0
    public int SpanLinq()
    {
        var items = CollectionsMarshal.AsSpan(source)
                    .Where(item => item.IsEven());
        var sum = 0;

        foreach (var item in items)
        {
            sum += item;
        }
        return(sum);
    }
    public FatValueType SpanLinq()
    {
        var items = CollectionsMarshal.AsSpan(source)
                    .Select(item => item * 3);
        var sum = default(FatValueType);

        foreach (var item in items)
        {
            sum += item;
        }
        return(sum);
    }
예제 #16
0
    public int SpanLinq()
    {
        var items = CollectionsMarshal.AsSpan(source)
                    .Select(item => item * 3);
        var sum = 0;

        foreach (var item in items)
        {
            sum += item;
        }
        return(sum);
    }
예제 #17
0
        internal static Span <byte> AssembleCall32(CallDescriptor32 callDescriptor)
        {
            var instructions = new List <byte>();

            foreach (var argument in callDescriptor.Arguments.Reverse())
            {
                if (argument <= sbyte.MaxValue)
                {
                    // push argument

                    instructions.AddRange(new byte[] { 0x6A, (byte)argument });
                }

                else
                {
                    // push argument

                    instructions.Add(0x68);

                    instructions.AddRange(BitConverter.GetBytes(argument));
                }
            }

            // mov eax, Address

            instructions.Add(0xB8);

            instructions.AddRange(BitConverter.GetBytes(callDescriptor.Address.ToInt32()));

            // call eax

            instructions.AddRange(new byte[] { 0xFF, 0xD0 });

            if (callDescriptor.ReturnAddress != IntPtr.Zero)
            {
                // mov ReturnAddress, eax

                instructions.Add(0xA3);

                instructions.AddRange(BitConverter.GetBytes(callDescriptor.ReturnAddress.ToInt32()));
            }

            // xor eax, eax

            instructions.AddRange(new byte[] { 0x33, 0xC0 });

            // ret

            instructions.Add(0xC3);

            return(CollectionsMarshal.AsSpan(instructions));
        }
예제 #18
0
    public FatValueType SpanLinq()
    {
        var items = CollectionsMarshal.AsSpan(source)
                    .Skip(Skip)
                    .Take(Count)
                    .Where(item => item.IsEven());
        var sum = default(FatValueType);

        foreach (var item in items)
        {
            sum += item;
        }
        return(sum);
    }
예제 #19
0
        public static Account SpanMax(this List <Account> items)
        {
            var span = CollectionsMarshal.AsSpan(items);
            var max  = span[span.Length - 1];

            for (int i = 0; i < span.Length; i++)
            {
                if (span[i].Amount > max.Amount)
                {
                    max = span[i];
                }
            }
            return(max);
        }
예제 #20
0
        /// <summary>
        /// Gets the length of a null terminated string pointer.
        /// </summary>
        public static unsafe string GetString(BufferedStreamReader reader, long offset, Encoding?encoding = null)
        {
            encoding ??= Encoding.ASCII;

            var bytes = new List <byte>(64);

            reader.Seek(offset, SeekOrigin.Begin);

            byte currentByte;

            while ((currentByte = reader.Read <byte>()) != 0)
            {
                bytes.Add(currentByte);
            }

            return(encoding.GetString(CollectionsMarshal.AsSpan(bytes)));
        }
예제 #21
0
        public void RemoveRange(int index, int count)
        {
            lock (SyncRoot)
            {
#if NET5_0_OR_GREATER
                var range = CollectionsMarshal.AsSpan(list).Slice(index, count);
#else
                var range = list.GetRange(index, count);
#endif

                // require copy before remove
                using (var xs = new CloneCollection <T>(range))
                {
                    list.RemoveRange(index, count);
                    CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs <T> .Remove(xs.Span, index));
                }
            }
        }
예제 #22
0
        private static bool IsInheritedProperty(PropertyInfo property, object others)
        {
            if (others is PropertyInfo single)
            {
                return(single.GetMethod?.GetBaseDefinition() == property.GetMethod?.GetBaseDefinition());
            }

            var many = (List <PropertyInfo>)others;

            foreach (var other in CollectionsMarshal.AsSpan(many))
            {
                if (other.GetMethod?.GetBaseDefinition() == property.GetMethod?.GetBaseDefinition())
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #23
0
        private static ushort** ReverseStringsImpl(ushort** strArray, int* numValues)
        {
            if (strArray == null)
            {
                *numValues = 0;
                return null;
            }

            List<IntPtr> newStrings = new List<IntPtr>();
            for (int i = 0; (nint)strArray[i] != 0; i++)
            {
                newStrings.Add((IntPtr)Strings.Reverse(strArray[i]));
            }
            newStrings.Add(IntPtr.Zero);

            ushort** res = (ushort**)Marshal.AllocCoTaskMem(sizeof(ushort*) * newStrings.Count);
            CollectionsMarshal.AsSpan(newStrings).CopyTo(new Span<IntPtr>((IntPtr*)(res), newStrings.Count));
            *numValues = newStrings.Count;
            return res;
        }
예제 #24
0
        public void ListAsSpanValueType()
        {
            var list = new List <int>();

            foreach (int length in Enumerable.Range(0, 36))
            {
                list.Clear();
                ValidateContentEquality(list, CollectionsMarshal.AsSpan(list));

                for (int i = 0; i < length; i++)
                {
                    list.Add(i);
                }
                ValidateContentEquality(list, CollectionsMarshal.AsSpan(list));

                list.TrimExcess();
                ValidateContentEquality(list, CollectionsMarshal.AsSpan(list));

                list.Add(length + 1);
                ValidateContentEquality(list, CollectionsMarshal.AsSpan(list));
            }
예제 #25
0
        private static bool ContainsHttpMethod(List <string> httpMethods, string httpMethod)
        {
            var methods = CollectionsMarshal.AsSpan(httpMethods);

            for (var i = 0; i < methods.Length; i++)
            {
                // This is a fast path for when everything is using static HttpMethods instances.
                if (object.ReferenceEquals(methods[i], httpMethod))
                {
                    return(true);
                }
            }

            for (var i = 0; i < methods.Length; i++)
            {
                if (HttpMethods.Equals(methods[i], httpMethod))
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #26
0
        [MethodImpl(MethodImplOptions.AggressiveInlining)] // fast type checks that don't add a lot of overhead
        private static bool TryGetSpan <TSource>(this IEnumerable <TSource> source, out ReadOnlySpan <TSource> span)
        // This constraint isn't required, but the overheads involved here can be more substantial when TSource
        // is a reference type and generic implementations are shared.  So for now we're protecting ourselves
        // and forcing a conscious choice to remove this in the future, at which point it should be paired with
        // sufficient performance testing.
            where TSource : struct
        {
            if (source is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
            }

            // Use `GetType() == typeof(...)` rather than `is` to avoid cast helpers.  This is measurably cheaper
            // but does mean we could end up missing some rare cases where we could get a span but don't (e.g. a uint[]
            // masquerading as an int[]).  That's an acceptable tradeoff.  The Unsafe usage is only after we've
            // validated the exact type; this could be changed to a cast in the future if the JIT starts to recognize it.
            // We only pay the comparison/branching costs here for super common types we expect to be used frequently
            // with LINQ methods.

            bool result = true;

            if (source.GetType() == typeof(TSource[]))
            {
                span = Unsafe.As <TSource[]>(source);
            }
            else if (source.GetType() == typeof(List <TSource>))
            {
                span = CollectionsMarshal.AsSpan(Unsafe.As <List <TSource> >(source));
            }
            else
            {
                span   = default;
                result = false;
            }

            return(result);
        }
예제 #27
0
        internal static Span <byte> AssembleSyscall64(int syscallIndex)
        {
            var instructions = new List <byte>();

            // mov r10, rcx

            instructions.AddRange(new byte[] { 0x4C, 0x8B, 0xD1 });

            // mov eax, syscallIndex

            instructions.Add(0xB8);

            instructions.AddRange(BitConverter.GetBytes(syscallIndex));

            // syscall

            instructions.AddRange(new byte[] { 0xF, 0x5 });

            // ret

            instructions.Add(0xC3);

            return(CollectionsMarshal.AsSpan(instructions));
        }
예제 #28
0
        internal static Span <byte> AssembleSyscall32(int syscallIndex)
        {
            var instructions = new List <byte>();

            // mov eax, syscallIndex

            instructions.Add(0xB8);

            instructions.AddRange(BitConverter.GetBytes(syscallIndex));

            if (Environment.Is64BitOperatingSystem)
            {
                // call DWORD PTR ds:[Wow64Transition]

                instructions.AddRange(new byte[] { 0xFF, 0x15 });

                instructions.AddRange(BitConverter.GetBytes(NativeLibrary.GetExport(NativeLibrary.Load("ntdll.dll"), "Wow64Transition").ToInt32()));
            }

            else
            {
                // mov edx, esp

                instructions.AddRange(new byte[] { 0x89, 0xE2 });

                // sysenter

                instructions.AddRange(new byte[] { 0xF, 0x34 });
            }

            // ret

            instructions.Add(0xC3);

            return(CollectionsMarshal.AsSpan(instructions));
        }
예제 #29
0
 public static Span <T> AsSpan <T>(this List <T>?list)
 {
     return(CollectionsMarshal.AsSpan(list));
 }
예제 #30
0
        internal static Span <byte> AssembleCall64(CallDescriptor <long> callDescriptor)
        {
            var shellcode       = new List <byte>();
            var shadowSpaceSize = Constants.ShadowSpaceSize + sizeof(long) * Math.Max(0, callDescriptor.Arguments.Count - 4);

            // sub rsp, shadowSpaceSize

            shellcode.AddRange(new byte[] { 0x48, 0x83, 0xEC, (byte)shadowSpaceSize });

            if (callDescriptor.Arguments.Count > 0)
            {
                var argument = callDescriptor.Arguments[0];

                switch (argument)
                {
                case 0:
                {
                    // xor ecx, ecx

                    shellcode.AddRange(new byte[] { 0x31, 0xC9 });

                    break;
                }

                case >= int.MinValue and <= uint.MaxValue:
                {
                    // mov ecx, argument

                    shellcode.Add(0xB9);
                    shellcode.AddRange(BitConverter.GetBytes((int)argument));

                    break;
                }

                default:
                {
                    // mov rcx, argument

                    shellcode.AddRange(new byte[] { 0x48, 0xB9 });
                    shellcode.AddRange(BitConverter.GetBytes(argument));

                    break;
                }
                }
            }

            if (callDescriptor.Arguments.Count > 1)
            {
                var argument = callDescriptor.Arguments[1];

                switch (argument)
                {
                case 0:
                {
                    // xor edx, edx

                    shellcode.AddRange(new byte[] { 0x31, 0xD2 });

                    break;
                }

                case >= int.MinValue and <= uint.MaxValue:
                {
                    // mov edx, argument

                    shellcode.Add(0xBA);
                    shellcode.AddRange(BitConverter.GetBytes((int)argument));

                    break;
                }

                default:
                {
                    // mov rdx, argument

                    shellcode.AddRange(new byte[] { 0x48, 0xBA });
                    shellcode.AddRange(BitConverter.GetBytes(argument));

                    break;
                }
                }
            }

            if (callDescriptor.Arguments.Count > 2)
            {
                var argument = callDescriptor.Arguments[2];

                switch (argument)
                {
                case 0:
                {
                    // xor r8, r8

                    shellcode.AddRange(new byte[] { 0x4D, 0x31, 0xC0 });

                    break;
                }

                case >= int.MinValue and <= uint.MaxValue:
                {
                    // mov r8d, argument

                    shellcode.AddRange(new byte[] { 0x41, 0xB8 });
                    shellcode.AddRange(BitConverter.GetBytes((int)argument));

                    break;
                }

                default:
                {
                    // mov r8, argument

                    shellcode.AddRange(new byte[] { 0x49, 0xB8 });
                    shellcode.AddRange(BitConverter.GetBytes(argument));

                    break;
                }
                }
            }

            if (callDescriptor.Arguments.Count > 3)
            {
                var argument = callDescriptor.Arguments[3];

                switch (argument)
                {
                case 0:
                {
                    // xor r9, r9

                    shellcode.AddRange(new byte[] { 0x4D, 0x31, 0xC9 });

                    break;
                }

                case >= int.MinValue and <= uint.MaxValue:
                {
                    // mov r9d, argument

                    shellcode.AddRange(new byte[] { 0x41, 0xB9 });
                    shellcode.AddRange(BitConverter.GetBytes((int)argument));

                    break;
                }

                default:
                {
                    // mov r9, argument

                    shellcode.AddRange(new byte[] { 0x49, 0xB9 });
                    shellcode.AddRange(BitConverter.GetBytes(argument));

                    break;
                }
                }
            }

            if (callDescriptor.Arguments.Count > 4)
            {
                foreach (var argument in callDescriptor.Arguments.Skip(4).Reverse())
                {
                    switch (argument)
                    {
                    case >= sbyte.MinValue and <= sbyte.MaxValue:
                    {
                        // push argument

                        shellcode.AddRange(new byte[] { 0x6A, unchecked ((byte)argument) });

                        break;
                    }

                    case >= int.MinValue and <= int.MaxValue:
                    {
                        // push argument

                        shellcode.Add(0x68);
                        shellcode.AddRange(BitConverter.GetBytes((int)argument));

                        break;
                    }

                    default:
                    {
                        // mov rax, argument

                        shellcode.AddRange(new byte[] { 0x48, 0xB8 });
                        shellcode.AddRange(BitConverter.GetBytes(argument));

                        // push rax

                        shellcode.Add(0x50);

                        break;
                    }
                    }
                }
            }

            // mov rax, Address

            shellcode.AddRange(new byte[] { 0x48, 0xB8 });
            shellcode.AddRange(BitConverter.GetBytes(callDescriptor.Address.ToInt64()));

            // call rax

            shellcode.AddRange(new byte[] { 0xFF, 0xD0 });

            if (callDescriptor.ReturnAddress != IntPtr.Zero)
            {
                // mov [ReturnAddress], rax

                shellcode.AddRange(new byte[] { 0x48, 0xA3 });
                shellcode.AddRange(BitConverter.GetBytes(callDescriptor.ReturnAddress.ToInt64()));
            }

            // xor eax, eax

            shellcode.AddRange(new byte[] { 0x31, 0xC0 });

            // add rsp, shadowSpaceSize

            shellcode.AddRange(new byte[] { 0x48, 0x83, 0xC4, (byte)shadowSpaceSize });

            // ret

            shellcode.Add(0xC3);

            return(CollectionsMarshal.AsSpan(shellcode));
        }