public static VariableDefinition AddLocalVariable(this MethodDefinition m, TypeReference type, string name = "")
        {
            if (m.Module == null)
            {
                throw new NullReferenceException($"This method has yet to be added to the assembly and doesn't have a module. Please provide a module.");
            }

            return(m.AddLocalVariable(m.Module, type, name));
        }
 public static VariableDefinition AddLocalVariable <T>(this MethodDefinition m, ModuleDefinition module, string name = "")
 {
     return(m.AddLocalVariable(module, module.ImportReference(typeof(T)), name));
 }
예제 #3
0
        public static Instruction[] GetKeyCheck(MethodDefinition method,
                                                VariableDefinition key,
                                                VariableDefinition stringKey,
                                                VariableDefinition keyLength,
                                                FieldDefinition field,
                                                MethodDefinition fieldSpan,
                                                out Instruction lengthLast,
                                                out Instruction checkLast,
                                                out bool isAdvanced)
        {
            Span <byte> binary = utf8.GetBytes(field.Name).AsSpan();

            switch (binary.Length)
            {
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
            case 8:
                isAdvanced = false;
                return(ByteKeyNameCheck(out lengthLast, out checkLast));

            default:
                isAdvanced = true;
                return(SequenceEqualsCheck(binary.Length, out lengthLast, out checkLast));
            }

            Instruction[] ByteKeyNameCheck(out Instruction length, out Instruction check)
            {
                ulong id = GetKeyName(field.Name);

                List <Instruction> i = new List <Instruction>();

                i.AddRange(ILHelper.Ldloc(keyLength));

                length = ILHelper.Int(field.Name.Length);
                i.Add(length);

                i.AddRange(ILHelper.Ldloc(key));
                i.Add(ILHelper.ULong(id));

                if (id < int.MaxValue)
                {
                    i.Add(Instruction.Create(OpCodes.Conv_I8));
                }

                check = i[i.Count - 1];

                return(i.ToArray());
            }

            Instruction[] SequenceEqualsCheck(int binaryLength, out Instruction length, out Instruction last)
            {
                VariableDefinition v = method.AddLocalVariable(method.Module.ImportReference(typeof(ReadOnlySpan <byte>)));

                MethodReference seqEqual = null;

                MethodInfo[] methods = typeof(MemoryExtensions).GetMethods();
                for (int j = 0; j < methods.Length; j++)
                {
                    if (methods[j].Name == "SequenceEqual")
                    {
                        ParameterInfo[] para = methods[j].GetParameters();
                        if (para.Length == 2 && IsSameType(para[0].ParameterType, typeof(ReadOnlySpan <>)) && IsSameType(para[1].ParameterType, typeof(ReadOnlySpan <>)))
                        {
                            seqEqual = method.Module.ImportReference(methods[j]).MakeGenericMethod(method.Module.GetTypeReference <byte>());
                            break;
                        }
                    }
                }

                if (seqEqual == null)
                {
                    throw new NullReferenceException("Couldn't find the sequence equals method.");
                }

                List <Instruction> i = new List <Instruction>();

                i.AddRange(ILHelper.Ldloc(keyLength));

                length = ILHelper.Int(field.Name.Length);
                i.Add(length);

                i.AddRange(ILHelper.Ldloc(stringKey));
                i.Add(Instruction.Create(OpCodes.Call, fieldSpan));
                i.AddRange(ILHelper.Stloc(v));
                i.AddRange(ILHelper.Ldloc(v, true));
                i.Add(ILHelper.Int(GetHeaderLength(binaryLength)));
                i.Add(Instruction.Create(OpCodes.Call, method.Module.ImportReference(typeof(ReadOnlySpan <byte>).GetMethod("Slice", new[] { typeof(int) }))));
                i.Add(Instruction.Create(OpCodes.Call, seqEqual));

                last = i[i.Count - 1];

                return(i.ToArray());

                bool IsSameType(Type typeA, Type typeB)
                {
                    return($"{typeA.Namespace}.{typeA.Name}" == typeB.FullName);
                }
            }
        }