
/*
 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.classfile;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import static com.sun.tools.classfile.Annotation.*;
import static com.sun.tools.classfile.ConstantPool.*;
import static com.sun.tools.classfile.StackMapTable_attribute.*;
import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*;

/**
 * Write a ClassFile data structure to a file or stream.
 *
 *  <p><b>This is NOT part of any supported API.
 *  If you write code that depends on this, you do so at your own risk.
 *  This code and its internal interfaces are subject to change or
 *  deletion without notice.</b>
 */
public class ClassWriter {
    public ClassWriter() {
        attributeWriter = new AttributeWriter();
        constantPoolWriter = new ConstantPoolWriter();
        out = new ClassOutputStream();
    }

    /**
     * Write a ClassFile data structure to a file.
     */
    public void write(ClassFile classFile, File f) throws IOException {
        FileOutputStream f_out = new FileOutputStream(f);
        try {
            write(classFile, f_out);
        } finally {
            f_out.close();
        }
    }

    /**
     * Write a ClassFile data structure to a stream.
     */
    public void write(ClassFile classFile, OutputStream s) throws IOException {
        this.classFile = classFile;
        out.reset();
        write();
        out.writeTo(s);
    }

    protected void write() throws IOException {
        writeHeader();
        writeConstantPool();
        writeAccessFlags(classFile.access_flags);
        writeClassInfo();
        writeFields();
        writeMethods();
        writeAttributes(classFile.attributes);
    }

    protected void writeHeader() {
        out.writeInt(classFile.magic);
        out.writeShort(classFile.minor_version);
        out.writeShort(classFile.major_version);
    }

    protected void writeAccessFlags(AccessFlags flags) {
        out.writeShort(flags.flags);
    }

    protected void writeAttributes(Attributes attributes) {
        int size = attributes.size();
        out.writeShort(size);
        for (Attribute attr: attributes)
            attributeWriter.write(attr, out);
    }

    protected void writeClassInfo() {
        out.writeShort(classFile.this_class);
        out.writeShort(classFile.super_class);
        int[] interfaces = classFile.interfaces;
        out.writeShort(interfaces.length);
        for (int i: interfaces)
            out.writeShort(i);
    }

    protected void writeDescriptor(Descriptor d) {
        out.writeShort(d.index);
    }

    protected void writeConstantPool() {
        ConstantPool pool = classFile.constant_pool;
        int size = pool.size();
        out.writeShort(size);
        for (CPInfo cpInfo: pool.entries())
            constantPoolWriter.write(cpInfo, out);
    }

    protected void writeFields() throws IOException {
        Field[] fields = classFile.fields;
        out.writeShort(fields.length);
        for (Field f: fields)
            writeField(f);
    }

    protected void writeField(Field f) throws IOException {
        writeAccessFlags(f.access_flags);
        out.writeShort(f.name_index);
        writeDescriptor(f.descriptor);
        writeAttributes(f.attributes);
    }

    protected void writeMethods() throws IOException {
        Method[] methods = classFile.methods;
        out.writeShort(methods.length);
        for (Method m: methods) {
            writeMethod(m);
        }
    }

    protected void writeMethod(Method m) throws IOException {
        writeAccessFlags(m.access_flags);
        out.writeShort(m.name_index);
        writeDescriptor(m.descriptor);
        writeAttributes(m.attributes);
    }

    protected ClassFile classFile;
    protected ClassOutputStream out;
    protected AttributeWriter attributeWriter;
    protected ConstantPoolWriter constantPoolWriter;

    /**
     * Subtype of ByteArrayOutputStream with the convenience methods of
     * a DataOutputStream. Since ByteArrayOutputStream does not throw
     * IOException, there are no exceptions from the additional
     * convenience methods either,
     */
    protected static class ClassOutputStream extends ByteArrayOutputStream {
        public ClassOutputStream() {
            d = new DataOutputStream(this);
        }

        public void writeByte(int value) {
            try {
                d.writeByte(value);
            } catch (IOException ignore) {
            }
        }

        public void writeShort(int value) {
            try {
                d.writeShort(value);
            } catch (IOException ignore) {
            }
        }

        public void writeInt(int value) {
            try {
                d.writeInt(value);
            } catch (IOException ignore) {
            }
        }

        public void writeLong(long value) {
            try {
                d.writeLong(value);
            } catch (IOException ignore) {
            }
        }

        public void writeFloat(float value) {
            try {
                d.writeFloat(value);
            } catch (IOException ignore) {
            }
        }

        public void writeDouble(double value) {
            try {
                d.writeDouble(value);
            } catch (IOException ignore) {
            }
        }

        public void writeUTF(String value) {
            try {
                d.writeUTF(value);
            } catch (IOException ignore) {
            }
        }

        public void writeTo(ClassOutputStream s) {
            try {
                super.writeTo(s);
            } catch (IOException ignore) {
            }
        }

        private DataOutputStream d;
    }

    /**
     * Writer for the entries in the constant pool.
     */
    protected static class ConstantPoolWriter
           implements ConstantPool.Visitor<Integer,ClassOutputStream> {
        protected int write(CPInfo info, ClassOutputStream out) {
            out.writeByte(info.getTag());
            return info.accept(this, out);
        }

        public Integer visitClass(CONSTANT_Class_info info, ClassOutputStream out) {
            out.writeShort(info.name_index);
            return 1;
        }

        public Integer visitDouble(CONSTANT_Double_info info, ClassOutputStream out) {
            out.writeDouble(info.value);
            return 2;
        }

        public Integer visitFieldref(CONSTANT_Fieldref_info info, ClassOutputStream out) {
            writeRef(info, out);
            return 1;
        }

        public Integer visitFloat(CONSTANT_Float_info info, ClassOutputStream out) {
            out.writeFloat(info.value);
            return 1;
        }

        public Integer visitInteger(CONSTANT_Integer_info info, ClassOutputStream out) {
            out.writeInt(info.value);
            return 1;
        }

        public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ClassOutputStream out) {
            writeRef(info, out);
            return 1;
        }

        public Integer visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ClassOutputStream out) {
            out.writeShort(info.bootstrap_method_attr_index);
            out.writeShort(info.name_and_type_index);
            return 1;
        }

        public Integer visitLong(CONSTANT_Long_info info, ClassOutputStream out) {
            out.writeLong(info.value);
            return 2;
        }

        public Integer visitNameAndType(CONSTANT_NameAndType_info info, ClassOutputStream out) {
            out.writeShort(info.name_index);
            out.writeShort(info.type_index);
            return 1;
        }

        public Integer visitMethodHandle(CONSTANT_MethodHandle_info info, ClassOutputStream out) {
            out.writeByte(info.reference_kind.tag);
            out.writeShort(info.reference_index);
            return 1;
        }

        public Integer visitMethodType(CONSTANT_MethodType_info info, ClassOutputStream out) {
            out.writeShort(info.descriptor_index);
            return 1;
        }

        public Integer visitMethodref(CONSTANT_Methodref_info info, ClassOutputStream out) {
            return writeRef(info, out);
        }

        public Integer visitString(CONSTANT_String_info info, ClassOutputStream out) {
            out.writeShort(info.string_index);
            return 1;
        }

        public Integer visitUtf8(CONSTANT_Utf8_info info, ClassOutputStream out) {
            out.writeUTF(info.value);
            return 1;
        }

        protected Integer writeRef(CPRefInfo info, ClassOutputStream out) {
            out.writeShort(info.class_index);
            out.writeShort(info.name_and_type_index);
            return 1;
        }
    }

    /**
     * Writer for the different types of attribute.
     */
    protected static class AttributeWriter implements Attribute.Visitor<Void,ClassOutputStream> {
        public void write(Attributes attributes, ClassOutputStream out) {
            int size = attributes.size();
            out.writeShort(size);
            for (Attribute a: attributes)
                write(a, out);
        }

        // Note: due to the use of shared resources, this method is not reentrant.
        public void write(Attribute attr, ClassOutputStream out) {
            out.writeShort(attr.attribute_name_index);
            sharedOut.reset();
            attr.accept(this, sharedOut);
            out.writeInt(sharedOut.size());
            sharedOut.writeTo(out);
        }

        protected ClassOutputStream sharedOut = new ClassOutputStream();
        protected AnnotationWriter annotationWriter = new AnnotationWriter();

        public Void visitDefault(DefaultAttribute attr, ClassOutputStream out) {
            out.write(attr.info, 0, attr.info.length);
            return null;
        }

        public Void visitAnnotationDefault(AnnotationDefault_attribute attr, ClassOutputStream out) {
            annotationWriter.write(attr.default_value, out);
            return null;
        }

        public Void visitBootstrapMethods(BootstrapMethods_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.bootstrap_method_specifiers.length);
            for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsm : attr.bootstrap_method_specifiers) {
                out.writeShort(bsm.bootstrap_method_ref);
                int bsm_args_count = bsm.bootstrap_arguments.length;
                out.writeShort(bsm_args_count);
                for (int i : bsm.bootstrap_arguments) {
                    out.writeShort(i);
                }
            }
            return null;
        }

        public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.character_range_table.length);
            for (CharacterRangeTable_attribute.Entry e: attr.character_range_table)
                writeCharacterRangeTableEntry(e, out);
            return null;
        }

        protected void writeCharacterRangeTableEntry(CharacterRangeTable_attribute.Entry entry, ClassOutputStream out) {
            out.writeShort(entry.start_pc);
            out.writeShort(entry.end_pc);
            out.writeInt(entry.character_range_start);
            out.writeInt(entry.character_range_end);
            out.writeShort(entry.flags);
        }

        public Void visitCode(Code_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.max_stack);
            out.writeShort(attr.max_locals);
            out.writeInt(attr.code.length);
            out.write(attr.code, 0, attr.code.length);
            out.writeShort(attr.exception_table.length);
            for (Code_attribute.Exception_data e: attr.exception_table)
                writeExceptionTableEntry(e, out);
            new AttributeWriter().write(attr.attributes, out);
            return null;
        }

        protected void writeExceptionTableEntry(Code_attribute.Exception_data exception_data, ClassOutputStream out) {
            out.writeShort(exception_data.start_pc);
            out.writeShort(exception_data.end_pc);
            out.writeShort(exception_data.handler_pc);
            out.writeShort(exception_data.catch_type);
        }

        public Void visitCompilationID(CompilationID_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.compilationID_index);
            return null;
        }

        public Void visitConstantValue(ConstantValue_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.constantvalue_index);
            return null;
        }

        public Void visitDeprecated(Deprecated_attribute attr, ClassOutputStream out) {
            return null;
        }

        public Void visitEnclosingMethod(EnclosingMethod_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.class_index);
            out.writeShort(attr.method_index);
            return null;
        }

        public Void visitExceptions(Exceptions_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.exception_index_table.length);
            for (int i: attr.exception_index_table)
                out.writeShort(i);
            return null;
        }

        public Void visitInnerClasses(InnerClasses_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.classes.length);
            for (InnerClasses_attribute.Info info: attr.classes)
                writeInnerClassesInfo(info, out);
            return null;
        }

        protected void writeInnerClassesInfo(InnerClasses_attribute.Info info, ClassOutputStream out) {
            out.writeShort(info.inner_class_info_index);
            out.writeShort(info.outer_class_info_index);
            out.writeShort(info.inner_name_index);
            writeAccessFlags(info.inner_class_access_flags, out);
        }

        public Void visitLineNumberTable(LineNumberTable_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.line_number_table.length);
            for (LineNumberTable_attribute.Entry e: attr.line_number_table)
                writeLineNumberTableEntry(e, out);
            return null;
        }

        protected void writeLineNumberTableEntry(LineNumberTable_attribute.Entry entry, ClassOutputStream out) {
            out.writeShort(entry.start_pc);
            out.writeShort(entry.line_number);
        }

        public Void visitLocalVariableTable(LocalVariableTable_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.local_variable_table.length);
            for (LocalVariableTable_attribute.Entry e: attr.local_variable_table)
                writeLocalVariableTableEntry(e, out);
            return null;
        }

        protected void writeLocalVariableTableEntry(LocalVariableTable_attribute.Entry entry, ClassOutputStream out) {
            out.writeShort(entry.start_pc);
            out.writeShort(entry.length);
            out.writeShort(entry.name_index);
            out.writeShort(entry.descriptor_index);
            out.writeShort(entry.index);
        }

        public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.local_variable_table.length);
            for (LocalVariableTypeTable_attribute.Entry e: attr.local_variable_table)
                writeLocalVariableTypeTableEntry(e, out);
            return null;
        }

        protected void writeLocalVariableTypeTableEntry(LocalVariableTypeTable_attribute.Entry entry, ClassOutputStream out) {
            out.writeShort(entry.start_pc);
            out.writeShort(entry.length);
            out.writeShort(entry.name_index);
            out.writeShort(entry.signature_index);
            out.writeShort(entry.index);
        }

        public Void visitMethodParameters(MethodParameters_attribute attr, ClassOutputStream out) {
            out.writeByte(attr.method_parameter_table.length);
            for (MethodParameters_attribute.Entry e : attr.method_parameter_table) {
                out.writeShort(e.name_index);
                out.writeShort(e.flags);
            }
            return null;
        }

        public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, ClassOutputStream out) {
            annotationWriter.write(attr.annotations, out);
            return null;
        }

        public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, ClassOutputStream out) {
            annotationWriter.write(attr.annotations, out);
            return null;
        }

        public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
            annotationWriter.write(attr.annotations, out);
            return null;
        }

        public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
            annotationWriter.write(attr.annotations, out);
            return null;
        }

        public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
            out.writeByte(attr.parameter_annotations.length);
            for (Annotation[] annos: attr.parameter_annotations)
                annotationWriter.write(annos, out);
            return null;
        }

        public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
            out.writeByte(attr.parameter_annotations.length);
            for (Annotation[] annos: attr.parameter_annotations)
                annotationWriter.write(annos, out);
            return null;
        }

        public Void visitSignature(Signature_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.signature_index);
            return null;
        }

        public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, ClassOutputStream out) {
            out.write(attr.debug_extension, 0, attr.debug_extension.length);
            return null;
        }

        public Void visitSourceFile(SourceFile_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.sourcefile_index);
            return null;
        }

        public Void visitSourceID(SourceID_attribute attr, ClassOutputStream out) {
            out.writeShort(attr.sourceID_index);
            return null;
        }

        public Void visitStackMap(StackMap_attribute attr, ClassOutputStream out) {
            if (stackMapWriter == null)
                stackMapWriter = new StackMapTableWriter();

            out.writeShort(attr.entries.length);
            for (stack_map_frame f: attr.entries)
                stackMapWriter.write(f, out);
            return null;
        }

        public Void visitStackMapTable(StackMapTable_attribute attr, ClassOutputStream out) {
            if (stackMapWriter == null)
                stackMapWriter = new StackMapTableWriter();

            out.writeShort(attr.entries.length);
            for (stack_map_frame f: attr.entries)
                stackMapWriter.write(f, out);
            return null;
        }

        public Void visitSynthetic(Synthetic_attribute attr, ClassOutputStream out) {
            return null;
        }

        protected void writeAccessFlags(AccessFlags flags, ClassOutputStream p) {
            sharedOut.writeShort(flags.flags);
        }

        protected StackMapTableWriter stackMapWriter;
    }

    /**
     * Writer for the frames of StackMap and StackMapTable attributes.
     */
    protected static class StackMapTableWriter
            implements stack_map_frame.Visitor<Void,ClassOutputStream> {

        public void write(stack_map_frame frame, ClassOutputStream out) {
            out.write(frame.frame_type);
            frame.accept(this, out);
        }

        public Void visit_same_frame(same_frame frame, ClassOutputStream p) {
            return null;
        }

        public Void visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, ClassOutputStream out) {
            writeVerificationTypeInfo(frame.stack[0], out);
            return null;
        }

        public Void visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, ClassOutputStream out) {
            out.writeShort(frame.offset_delta);
            writeVerificationTypeInfo(frame.stack[0], out);
            return null;
        }

        public Void visit_chop_frame(chop_frame frame, ClassOutputStream out) {
            out.writeShort(frame.offset_delta);
            return null;
        }

        public Void visit_same_frame_extended(same_frame_extended frame, ClassOutputStream out) {
            out.writeShort(frame.offset_delta);
            return null;
        }

        public Void visit_append_frame(append_frame frame, ClassOutputStream out) {
            out.writeShort(frame.offset_delta);
            for (verification_type_info l: frame.locals)
                writeVerificationTypeInfo(l, out);
            return null;
        }

        public Void visit_full_frame(full_frame frame, ClassOutputStream out) {
            out.writeShort(frame.offset_delta);
            out.writeShort(frame.locals.length);
            for (verification_type_info l: frame.locals)
                writeVerificationTypeInfo(l, out);
            out.writeShort(frame.stack.length);
            for (verification_type_info s: frame.stack)
                writeVerificationTypeInfo(s, out);
            return null;
        }

        protected void writeVerificationTypeInfo(verification_type_info info,
                ClassOutputStream out)  {
            out.write(info.tag);
            switch (info.tag) {
            case ITEM_Top:
            case ITEM_Integer:
            case ITEM_Float:
            case ITEM_Long:
            case ITEM_Double:
            case ITEM_Null:
            case ITEM_UninitializedThis:
                break;

            case ITEM_Object:
                Object_variable_info o = (Object_variable_info) info;
                out.writeShort(o.cpool_index);
                break;

            case ITEM_Uninitialized:
                Uninitialized_variable_info u = (Uninitialized_variable_info) info;
                out.writeShort(u.offset);
                break;

            default:
                throw new Error();
            }
        }
    }

    /**
     * Writer for annotations and the values they contain.
     */
    protected static class AnnotationWriter
            implements Annotation.element_value.Visitor<Void,ClassOutputStream> {
        public void write(Annotation[] annos, ClassOutputStream out) {
            out.writeShort(annos.length);
            for (Annotation anno: annos)
                write(anno, out);
        }

        public void write(TypeAnnotation[] annos, ClassOutputStream out) {
            out.writeShort(annos.length);
            for (TypeAnnotation anno: annos)
                write(anno, out);
        }

        public void write(Annotation anno, ClassOutputStream out) {
            out.writeShort(anno.type_index);
            out.writeShort(anno.element_value_pairs.length);
            for (element_value_pair p: anno.element_value_pairs)
                write(p, out);
        }

        public void write(TypeAnnotation anno, ClassOutputStream out) {
            write(anno.position, out);
            write(anno.annotation, out);
        }

        public void write(element_value_pair pair, ClassOutputStream out) {
            out.writeShort(pair.element_name_index);
            write(pair.value, out);
        }

        public void write(element_value ev, ClassOutputStream out) {
            out.writeByte(ev.tag);
            ev.accept(this, out);
        }

        public Void visitPrimitive(Primitive_element_value ev, ClassOutputStream out) {
            out.writeShort(ev.const_value_index);
            return null;
        }

        public Void visitEnum(Enum_element_value ev, ClassOutputStream out) {
            out.writeShort(ev.type_name_index);
            out.writeShort(ev.const_name_index);
            return null;
        }

        public Void visitClass(Class_element_value ev, ClassOutputStream out) {
            out.writeShort(ev.class_info_index);
            return null;
        }

        public Void visitAnnotation(Annotation_element_value ev, ClassOutputStream out) {
            write(ev.annotation_value, out);
            return null;
        }

        public Void visitArray(Array_element_value ev, ClassOutputStream out) {
            out.writeShort(ev.num_values);
            for (element_value v: ev.values)
                write(v, out);
            return null;
        }

        // TODO: Move this to TypeAnnotation to be closer with similar logic?
        private void write(TypeAnnotation.Position p, ClassOutputStream out) {
            out.writeByte(p.type.targetTypeValue());
            switch (p.type) {
            // instanceof
            case INSTANCEOF:
            // new expression
            case NEW:
            // constructor/method reference receiver
            case CONSTRUCTOR_REFERENCE:
            case METHOD_REFERENCE:
                out.writeShort(p.offset);
                break;
            // local variable
            case LOCAL_VARIABLE:
            // resource variable
            case RESOURCE_VARIABLE:
                int table_length = p.lvarOffset.length;
                out.writeShort(table_length);
                for (int i = 0; i < table_length; ++i) {
                    out.writeShort(1);  // for table length
                    out.writeShort(p.lvarOffset[i]);
                    out.writeShort(p.lvarLength[i]);
                    out.writeShort(p.lvarIndex[i]);
                }
                break;
            // exception parameter
            case EXCEPTION_PARAMETER:
                out.writeShort(p.exception_index);
                break;
            // method receiver
            case METHOD_RECEIVER:
                // Do nothing
                break;
            // type parameters
            case CLASS_TYPE_PARAMETER:
            case METHOD_TYPE_PARAMETER:
                out.writeByte(p.parameter_index);
                break;
            // type parameters bounds
            case CLASS_TYPE_PARAMETER_BOUND:
            case METHOD_TYPE_PARAMETER_BOUND:
                out.writeByte(p.parameter_index);
                out.writeByte(p.bound_index);
                break;
            // class extends or implements clause
            case CLASS_EXTENDS:
                out.writeShort(p.type_index);
                break;
            // throws
            case THROWS:
                out.writeShort(p.type_index);
                break;
            // method parameter
            case METHOD_FORMAL_PARAMETER:
                out.writeByte(p.parameter_index);
                break;
            // type cast
            case CAST:
            // method/constructor/reference type argument
            case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
            case METHOD_INVOCATION_TYPE_ARGUMENT:
            case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
            case METHOD_REFERENCE_TYPE_ARGUMENT:
                out.writeShort(p.offset);
                out.writeByte(p.type_index);
                break;
            // We don't need to worry about these
            case METHOD_RETURN:
            case FIELD:
                break;
            case UNKNOWN:
                throw new AssertionError("ClassWriter: UNKNOWN target type should never occur!");
            default:
                throw new AssertionError("ClassWriter: Unknown target type for position: " + p);
            }

            { // Append location data for generics/arrays.
                // TODO: check for overrun?
                out.writeByte((byte)p.location.size());
                for (int i : TypeAnnotation.Position.getBinaryFromTypePath(p.location))
                    out.writeByte((byte)i);
            }
        }
    }
}
