internal static void WriteAttribute(Stream stream, AttributeNode attribute, ClassWriterState state, AttributeScope scope) { Binary.BigEndian.Write(stream, state.ConstantPool.Find(new Utf8Entry(attribute.Name))); attribute.Data = attribute.ParsedAttribute?.Save(state, scope) ?? attribute.Data; if (attribute.Data.LongLength > uint.MaxValue) { throw new ArgumentOutOfRangeException(nameof(attribute.Data.LongLength), $"Attribute data length too big: {attribute.Data.LongLength} > {uint.MaxValue}"); } Binary.BigEndian.Write(stream, (uint)attribute.Data.LongLength); stream.Write(attribute.Data); }
private static void WriteMethod(Stream stream, MethodNode methodNode, ClassWriterState state) { Binary.BigEndian.Write(stream, (ushort)methodNode.Access); Binary.BigEndian.Write(stream, state.ConstantPool.Find(new Utf8Entry(methodNode.Name))); Binary.BigEndian.Write(stream, state.ConstantPool.Find(new Utf8Entry(methodNode.Descriptor.ToString()))); if (methodNode.Attributes.Count > ushort.MaxValue) { throw new ArgumentOutOfRangeException(nameof(methodNode.Attributes.Count), $"Too many attributes: {methodNode.Attributes.Count} > {ushort.MaxValue}"); } Binary.BigEndian.Write(stream, (ushort)methodNode.Attributes.Count); foreach (var attriute in methodNode.Attributes) { WriteAttribute(stream, attriute, state, AttributeScope.Method); } }
public static void WriteClass(Stream stream, ClassNode classNode) { Binary.BigEndian.Write(stream, Magic); Binary.BigEndian.Write(stream, classNode.MinorVersion); Binary.BigEndian.Write(stream, (ushort)classNode.MajorVersion); var afterConstantPoolDataStream = new MemoryStream(); var constantPool = new ConstantPool(); var state = new ClassWriterState { ClassNode = classNode, ConstantPool = constantPool }; classNode.Save(state); Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Access); Binary.BigEndian.Write(afterConstantPoolDataStream, constantPool.Find(new ClassEntry(new Utf8Entry(classNode.Name.Name)))); Binary.BigEndian.Write(afterConstantPoolDataStream, constantPool.Find(new ClassEntry(new Utf8Entry(classNode.SuperName.Name)))); if (classNode.Interfaces.Count > ushort.MaxValue) { throw new ArgumentOutOfRangeException(nameof(classNode.Interfaces.Count), $"Too many interfaces: {classNode.Interfaces.Count} > {ushort.MaxValue}"); } Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Interfaces.Count); foreach (var interfaceClassName in classNode.Interfaces) { Binary.BigEndian.Write(afterConstantPoolDataStream, constantPool.Find(new ClassEntry(new Utf8Entry(interfaceClassName.Name)))); } if (classNode.Fields.Count > ushort.MaxValue) { throw new ArgumentOutOfRangeException(nameof(classNode.Fields.Count), $"Too many fields: {classNode.Fields.Count} > {ushort.MaxValue}"); } Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Fields.Count); foreach (var field in classNode.Fields) { WriteField(afterConstantPoolDataStream, field, state); } if (classNode.Methods.Count > ushort.MaxValue) { throw new ArgumentOutOfRangeException(nameof(classNode.Methods.Count), $"Too many methods: {classNode.Methods.Count} > {ushort.MaxValue}"); } Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Methods.Count); foreach (var method in classNode.Methods) { WriteMethod(afterConstantPoolDataStream, method, state); } if (classNode.Attributes.Count > ushort.MaxValue) { throw new ArgumentOutOfRangeException(nameof(classNode.Attributes.Count), $"Too many attributes: {classNode.Attributes.Count} > {ushort.MaxValue}"); } Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Attributes.Count); foreach (var attriute in classNode.Attributes) { WriteAttribute(afterConstantPoolDataStream, attriute, state, AttributeScope.Class); } constantPool.Write(stream); stream.Write(afterConstantPoolDataStream.ToArray()); }