private static AttributeCode ReadAttributeCode(BytecodeReader reader, ConstantPool cp)
        {
            ushort attributeNameIndex = reader.ReadUShort();

            uint attributesLength = reader.ReadUInt();

            ushort maxStack = reader.ReadUShort();

            ushort maxLocals = reader.ReadUShort();

            uint codeLength = reader.ReadUInt();

            // typecasting could be bad
            byte[] bytecode = reader.ReadArray((int)codeLength);

            ushort exceptionTableLength = reader.ReadUShort();

            byte[] exceptionTable = reader.ReadArray(exceptionTableLength * 8);

            ushort attributesCount = reader.ReadUShort();

            Attributes attributes = ReadAttributes(reader, attributesCount, cp);

            return(new AttributeCode(attributeNameIndex, attributesLength, maxStack, maxLocals,
                                     codeLength, bytecode, exceptionTableLength, exceptionTable, attributesCount, attributes));
        }
        private static AttributeConstantValue ReadAttributeConstantValue(BytecodeReader reader)
        {
            ushort attributeNameIndex = reader.ReadUShort();

            uint attributeLength = reader.ReadUInt();

            return(new AttributeConstantValue(attributeNameIndex, attributeLength));
        }
        private static AttributeBootstrapMethods ReadAttributeBootstrapMethods(BytecodeReader reader)
        {
            ushort attributeNameIndex = reader.ReadUShort();

            uint attributeLength = reader.ReadUInt();

            return(new AttributeBootstrapMethods(attributeNameIndex, attributeLength));
        }
        private static AttributeStackMapTable ReadAttributeStackMapTable(BytecodeReader reader)
        {
            ushort attributeNameIndex = reader.ReadUShort();

            uint attributeLength = reader.ReadUInt();

            ushort numberOfEntries = reader.ReadUShort();

            return(new AttributeStackMapTable(attributeNameIndex, attributeLength, numberOfEntries));
        }
        private static AttributeSourceFile ReadAttributeSourceFile(BytecodeReader reader)
        {
            ushort attributeNameIndex = reader.ReadUShort();

            uint attributeLength = reader.ReadUInt();

            ushort sourceFileIndex = reader.ReadUShort();

            return(new AttributeSourceFile(attributeNameIndex, attributeLength, sourceFileIndex));
        }
        public static JavaClass ReadJavaClass(byte[] bytecode)
        {
            BytecodeReader reader = new BytecodeReader(bytecode);

            // ca fe ba be
            uint magic = reader.ReadUInt();

            // Версии
            ushort minorVersion      = reader.ReadUShort();
            ushort majorVersion      = reader.ReadUShort();
            ushort constantPoolCount = reader.ReadUShort();

            ConstantPool constantPool = ReadConstantPool(reader, constantPoolCount);

            ushort accessFlags = reader.ReadUShort();
            // Индекс констанnы class текущего класса в пуле констант
            ushort thisClass       = reader.ReadUShort();
            ushort superClass      = reader.ReadUShort();
            ushort interfacesCount = reader.ReadUShort();

            Interfaces interfaces = ReadInterfaces(reader, interfacesCount, constantPool);

            ushort       fieldsCount = reader.ReadUShort();
            List <Field> fields      = new List <Field>();

            for (int i = 0; i < fieldsCount; i++)
            {
                fields.Add(ReadField(reader, fieldsCount, constantPool));
            }

            ushort        methodsCount = reader.ReadUShort();
            List <Method> methods      = new List <Method>();

            for (short i = 0; i < methodsCount; i++)
            {
                methods.Add(ReadMethod(reader, methodsCount, constantPool));
            }

            ushort attributesCount = reader.ReadUShort();

            Attributes attributes = ReadAttributes(reader, attributesCount, constantPool);

            return(new JavaClass(magic, minorVersion, majorVersion, constantPoolCount, constantPool, accessFlags,
                                 thisClass, superClass, interfacesCount, interfaces, fieldsCount, fields, methodsCount,
                                 methods, attributesCount, attributes));
        }
        private static AttributeLineNumberTable ReadAttributeLineNumberTable(BytecodeReader reader)
        {
            ushort attributeNameIndex = reader.ReadUShort();

            uint attributeLength = reader.ReadUInt();

            ushort lineNumberTableLength = reader.ReadUShort();

            List <byte[]> startPC    = new List <byte[]>();
            List <byte[]> lineNumber = new List <byte[]>();

            for (int i = 0; i < lineNumberTableLength; i++)
            {
                startPC.Add(reader.ReadArray(2));
                lineNumber.Add(reader.ReadArray(2));
            }
            return(new AttributeLineNumberTable(attributeNameIndex, attributeLength,
                                                lineNumberTableLength, startPC, lineNumber));
        }