// Copyright 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gwtorm.protobuf;

import com.google.gwtorm.client.Column;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.jdbc.gen.CodeGenSupport;
import com.google.gwtorm.schema.ColumnModel;
import com.google.gwtorm.schema.Util;
import com.google.gwtorm.schema.java.JavaColumnModel;
import com.google.gwtorm.server.GeneratedClassLoader;
import com.google.protobuf.ByteString;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.CodedOutputStream;
import com.google.protobuf.WireFormat;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;

/** Generates {@link ProtobufCodec} implementations. */
class CodecGen<T> implements Opcodes {
  private static final Type string = Type.getType(String.class);
  private static final Type byteStringOutput =
      Type.getType(ByteString.Output.class);
  private static final Type byteString = Type.getType(ByteString.class);
  private static final Type object = Type.getType(Object.class);
  private static final Type codedOutputStream =
      Type.getType(CodedOutputStream.class);
  private static final Type codedInputStream =
      Type.getType(CodedInputStream.class);
  private final GeneratedClassLoader classLoader;
  private final Class<T> pojo;
  private final Type pojoType;

  private ClassWriter cw;
  private JavaColumnModel[] myFields;
  private String superTypeName;
  private String implClassName;
  private String implTypeName;

  public CodecGen(final GeneratedClassLoader loader, final Class<T> t) {
    classLoader = loader;
    pojo = t;
    pojoType = Type.getType(pojo);
  }

  public ProtobufCodec<T> create() throws OrmException {
    myFields = scanFields(pojo);

    init();
    implementConstructor();
    implementSizeof();
    implementEncode();
    implementDecode();
    cw.visitEnd();
    classLoader.defineClass(implClassName, cw.toByteArray());

    try {
      final Class<?> c = Class.forName(implClassName, true, classLoader);
      return cast(c.newInstance());
    } catch (InstantiationException e) {
      throw new OrmException("Cannot create new encoder", e);
    } catch (IllegalAccessException e) {
      throw new OrmException("Cannot create new encoder", e);
    } catch (ClassNotFoundException e) {
      throw new OrmException("Cannot create new encoder", e);
    }
  }

  private static JavaColumnModel[] scanFields(Class<?> in) throws OrmException {
    final Collection<JavaColumnModel> col = new ArrayList<JavaColumnModel>();
    while (in != null) {
      for (final Field f : in.getDeclaredFields()) {
        if (f.getAnnotation(Column.class) != null) {
          col.add(new JavaColumnModel(f));
        }
      }
      in = in.getSuperclass();
    }
    return sort(col);
  }

  private static JavaColumnModel[] sort(
      final Collection<? extends ColumnModel> col) {
    JavaColumnModel[] out = col.toArray(new JavaColumnModel[col.size()]);
    Arrays.sort(out, new Comparator<JavaColumnModel>() {
      @Override
      public int compare(JavaColumnModel o1, JavaColumnModel o2) {
        return o1.getColumnID() - o2.getColumnID();
      }
    });
    return out;
  }

  @SuppressWarnings("unchecked")
  private static <T> ProtobufCodec<T> cast(final Object c) {
    return (ProtobufCodec<T>) c;
  }

  private void init() {
    superTypeName = Type.getInternalName(ProtobufCodec.class);
    implClassName = pojo.getName() + "_protobuf_" + Util.createRandomName();
    implTypeName = implClassName.replace('.', '/');

    cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    cw.visit(V1_3, ACC_PUBLIC | ACC_FINAL | ACC_SUPER, implTypeName, null,
        superTypeName, new String[] {});
  }

  private void implementConstructor() {
    final String consName = "<init>";
    final String consDesc =
        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {});
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC, consName, consDesc, null, null);
    mv.visitCode();

    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, superTypeName, consName, consDesc);

    mv.visitInsn(RETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private void implementSizeof() throws OrmException {
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC, "sizeof", Type.getMethodDescriptor(
            Type.INT_TYPE, new Type[] {object}), null, new String[] {});
    mv.visitCode();
    final SizeofCGS cgs = new SizeofCGS(mv);
    cgs.setEntityType(pojoType);

    mv.visitVarInsn(ALOAD, 1);
    mv.visitTypeInsn(CHECKCAST, pojoType.getInternalName());
    mv.visitVarInsn(ASTORE, 1);

    cgs.push(0);
    mv.visitVarInsn(ISTORE, cgs.sizeVar);
    sizeofMessage(myFields, mv, cgs);

    mv.visitVarInsn(ILOAD, cgs.sizeVar);
    mv.visitInsn(IRETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private static void sizeofMessage(final JavaColumnModel[] myFields,
      final MethodVisitor mv, final SizeofCGS cgs) throws OrmException {
    for (final JavaColumnModel f : myFields) {
      if (f.isNested()) {
        final Label end = new Label();
        cgs.setFieldReference(f);
        cgs.pushFieldValue();
        mv.visitJumpInsn(IFNULL, end);

        final int oldVar = cgs.sizeVar;
        final int msgVar = cgs.newLocal();
        cgs.sizeVar = msgVar;
        cgs.push(0);
        mv.visitVarInsn(ISTORE, cgs.sizeVar);

        sizeofMessage(sort(f.getNestedColumns()), mv, cgs);
        cgs.sizeVar = oldVar;

        cgs.push(f.getColumnID());
        cgs.inc("computeTagSize", Type.INT_TYPE);

        mv.visitVarInsn(ILOAD, msgVar);
        cgs.inc("computeRawVarint32Size", Type.INT_TYPE);

        mv.visitVarInsn(ILOAD, msgVar);
        cgs.inc();

        cgs.freeLocal(msgVar);
        mv.visitLabel(end);
      } else {
        sizeofScalar(mv, cgs, f);
      }
    }
  }

  private static void sizeofScalar(final MethodVisitor mv, final SizeofCGS cgs,
      final JavaColumnModel f) throws OrmException {
    cgs.setFieldReference(f);

    switch (Type.getType(f.getPrimitiveType()).getSort()) {
      case Type.BOOLEAN:
        cgs.push(f.getColumnID());
        cgs.pushFieldValue();
        cgs.inc("computeBoolSize", Type.INT_TYPE, Type.BOOLEAN_TYPE);
        break;

      case Type.CHAR:
        cgs.push(f.getColumnID());
        cgs.pushFieldValue();
        cgs.inc("computeUInt32Size", Type.INT_TYPE, Type.INT_TYPE);
        break;

      case Type.BYTE:
      case Type.SHORT:
      case Type.INT:
        cgs.push(f.getColumnID());
        cgs.pushFieldValue();
        cgs.inc("computeSInt32Size", Type.INT_TYPE, Type.INT_TYPE);
        break;

      case Type.FLOAT:
        cgs.push(f.getColumnID());
        cgs.pushFieldValue();
        cgs.inc("computeFloatSize", Type.INT_TYPE, Type.FLOAT_TYPE);
        break;

      case Type.DOUBLE:
        cgs.push(f.getColumnID());
        cgs.pushFieldValue();
        cgs.inc("computeDoubleSize", Type.INT_TYPE, Type.DOUBLE_TYPE);
        break;

      case Type.LONG:
        cgs.push(f.getColumnID());
        cgs.pushFieldValue();
        cgs.inc("computeSInt64", Type.INT_TYPE, Type.LONG_TYPE);
        break;

      case Type.ARRAY:
      case Type.OBJECT: {
        final Label end = new Label();
        cgs.pushFieldValue();
        mv.visitJumpInsn(IFNULL, end);

        if (f.getPrimitiveType() == byte[].class) {
          cgs.push(f.getColumnID());
          cgs.inc("computeTagSize", Type.INT_TYPE);

          cgs.pushFieldValue();
          mv.visitInsn(ARRAYLENGTH);
          cgs.inc("computeRawVarint32Size", Type.INT_TYPE);

          cgs.pushFieldValue();
          mv.visitInsn(ARRAYLENGTH);
          cgs.inc();

        } else if (f.getPrimitiveType() == String.class) {
          cgs.push(f.getColumnID());
          cgs.pushFieldValue();
          cgs.inc("computeStringSize", Type.INT_TYPE, string);

        } else if (f.getPrimitiveType() == java.sql.Timestamp.class
            || f.getPrimitiveType() == java.util.Date.class
            || f.getPrimitiveType() == java.sql.Date.class) {
          cgs.push(f.getColumnID());
          String tsType = Type.getType(f.getPrimitiveType()).getInternalName();
          mv.visitMethodInsn(INVOKEVIRTUAL, tsType, "getTime", Type
              .getMethodDescriptor(Type.LONG_TYPE, new Type[] {}));
          cgs.inc("computeFixed64Size", Type.INT_TYPE, Type.LONG_TYPE);

        } else {
          throw new OrmException("Type " + f.getPrimitiveType()
              + " not supported for field " + f.getPathToFieldName());
        }
        mv.visitLabel(end);
        break;
      }

      default:
        throw new OrmException("Type " + f.getPrimitiveType()
            + " not supported for field " + f.getPathToFieldName());
    }
  }

  private void implementEncode() throws OrmException {
    final MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC, "encode", Type.getMethodDescriptor(
            byteString, new Type[] {object}), null, new String[] {});
    mv.visitCode();
    final EncodeCGS cgs = new EncodeCGS(mv);
    cgs.setEntityType(pojoType);

    mv.visitVarInsn(ALOAD, 1);
    mv.visitTypeInsn(CHECKCAST, pojoType.getInternalName());
    mv.visitVarInsn(ASTORE, 1);

    encodeMessage(myFields, mv, cgs);

    mv.visitInsn(ARETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private static void encodeMessage(final JavaColumnModel[] myFields,
      final MethodVisitor mv, final EncodeCGS cgs) throws OrmException {
    final int oldVar = cgs.codedOutputStreamVar;
    cgs.codedOutputStreamVar = cgs.newLocal();

    final int strVar = cgs.newLocal();
    mv.visitMethodInsn(INVOKESTATIC, byteString.getInternalName(), "newOutput",
        Type.getMethodDescriptor(byteStringOutput, new Type[] {}));
    mv.visitVarInsn(ASTORE, strVar);

    mv.visitVarInsn(ALOAD, strVar);
    mv.visitMethodInsn(INVOKESTATIC, codedOutputStream.getInternalName(),
        "newInstance", Type.getMethodDescriptor(codedOutputStream,
            new Type[] {Type.getType(OutputStream.class)}));
    mv.visitVarInsn(ASTORE, cgs.codedOutputStreamVar);

    for (final JavaColumnModel f : myFields) {
      if (f.isNested()) {
        final Label end = new Label();
        cgs.setFieldReference(f);
        cgs.pushFieldValue();
        mv.visitJumpInsn(IFNULL, end);

        final int v = cgs.newLocal();
        encodeMessage(sort(f.getNestedColumns()), mv, cgs);
        mv.visitVarInsn(ASTORE, v);

        mv.visitVarInsn(ALOAD, v);
        mv.visitMethodInsn(INVOKEVIRTUAL, byteString.getInternalName(), "size",
            Type.getMethodDescriptor(Type.INT_TYPE, new Type[] {}));
        mv.visitJumpInsn(IFEQ, end);

        cgs.pushCodedOutputStream();
        cgs.push(f.getColumnID());
        mv.visitVarInsn(ALOAD, v);
        cgs.write("writeBytes", byteString);

        cgs.freeLocal(v);
        mv.visitLabel(end);
      } else {
        encodeScalar(mv, cgs, f);
      }
    }

    cgs.pushCodedOutputStream();
    mv.visitMethodInsn(INVOKEVIRTUAL, codedOutputStream.getInternalName(),
        "flush", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}));

    cgs.freeLocal(cgs.codedOutputStreamVar);
    cgs.codedOutputStreamVar = oldVar;

    mv.visitVarInsn(ALOAD, strVar);
    mv.visitMethodInsn(INVOKEVIRTUAL, byteStringOutput.getInternalName(),
        "toByteString", Type.getMethodDescriptor(byteString, new Type[] {}));
    cgs.freeLocal(strVar);
  }

  private static void encodeScalar(final MethodVisitor mv, final EncodeCGS cgs,
      final JavaColumnModel f) throws OrmException {
    cgs.setFieldReference(f);

    switch (Type.getType(f.getPrimitiveType()).getSort()) {
      case Type.BOOLEAN:
        cgs.pushCodedOutputStream();
        cgs.push(f.getColumnID());
        cgs.pushFieldValue();
        cgs.write("writeBool", Type.BOOLEAN_TYPE);
        break;

      case Type.CHAR:
        cgs.pushCodedOutputStream();
        cgs.push(f.getColumnID());
        cgs.pushFieldValue();
        cgs.write("writeUInt32", Type.INT_TYPE);
        break;

      case Type.BYTE:
      case Type.SHORT:
      case Type.INT:
        cgs.pushCodedOutputStream();
        cgs.push(f.getColumnID());
        cgs.pushFieldValue();
        cgs.write("writeSInt32", Type.INT_TYPE);
        break;

      case Type.FLOAT:
        cgs.pushCodedOutputStream();
        cgs.push(f.getColumnID());
        cgs.pushFieldValue();
        cgs.write("writeFloat", Type.FLOAT_TYPE);
        break;

      case Type.DOUBLE:
        cgs.pushCodedOutputStream();
        cgs.push(f.getColumnID());
        cgs.pushFieldValue();
        cgs.write("writeDouble", Type.DOUBLE_TYPE);
        break;

      case Type.LONG:
        cgs.pushCodedOutputStream();
        cgs.push(f.getColumnID());
        cgs.pushFieldValue();
        cgs.write("writeSInt64", Type.LONG_TYPE);
        break;

      case Type.ARRAY:
      case Type.OBJECT: {
        final Label end = new Label();
        cgs.pushFieldValue();
        mv.visitJumpInsn(IFNULL, end);

        if (f.getPrimitiveType() == byte[].class) {
          cgs.pushCodedOutputStream();
          cgs.push(f.getColumnID());
          cgs.push(WireFormat.FieldType.BYTES.getWireType());
          mv.visitMethodInsn(INVOKEVIRTUAL,
              codedOutputStream.getInternalName(), "writeTag", Type
                  .getMethodDescriptor(Type.VOID_TYPE, new Type[] {
                      Type.INT_TYPE, Type.INT_TYPE}));

          cgs.pushCodedOutputStream();
          cgs.pushFieldValue();
          mv.visitInsn(ARRAYLENGTH);
          mv.visitMethodInsn(INVOKEVIRTUAL,
              codedOutputStream.getInternalName(), "writeRawVarint32", Type
                  .getMethodDescriptor(Type.VOID_TYPE,
                      new Type[] {Type.INT_TYPE}));

          cgs.pushCodedOutputStream();
          cgs.pushFieldValue();
          mv.visitMethodInsn(INVOKEVIRTUAL,
              codedOutputStream.getInternalName(), "writeRawBytes", Type
                  .getMethodDescriptor(Type.VOID_TYPE, new Type[] {Type
                      .getType(byte[].class)}));

        } else {
          cgs.pushCodedOutputStream();
          cgs.push(f.getColumnID());
          cgs.pushFieldValue();

          if (f.getPrimitiveType() == String.class) {
            cgs.write("writeString", string);

          } else if (f.getPrimitiveType() == java.sql.Timestamp.class
              || f.getPrimitiveType() == java.util.Date.class
              || f.getPrimitiveType() == java.sql.Date.class) {
            String tsType =
                Type.getType(f.getPrimitiveType()).getInternalName();
            mv.visitMethodInsn(INVOKEVIRTUAL, tsType, "getTime", Type
                .getMethodDescriptor(Type.LONG_TYPE, new Type[] {}));
            cgs.write("writeFixed64", Type.LONG_TYPE);

          } else {
            throw new OrmException("Type " + f.getPrimitiveType()
                + " not supported for field " + f.getPathToFieldName());
          }
        }
        mv.visitLabel(end);
        break;
      }

      default:
        throw new OrmException("Type " + f.getPrimitiveType()
            + " not supported for field " + f.getPathToFieldName());
    }
  }

  private void implementDecode() throws OrmException {
    final Type retType = object;
    final MethodVisitor mv =
        cw.visitMethod(ACC_PROTECTED, "decode", Type.getMethodDescriptor(
            retType, new Type[] {codedInputStream}), null, new String[] {});
    mv.visitCode();
    final DecodeCGS cgs = new DecodeCGS(mv);

    cgs.setEntityType(pojoType);

    mv.visitTypeInsn(NEW, pojoType.getInternalName());
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESPECIAL, pojoType.getInternalName(), "<init>",
        Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}));
    mv.visitVarInsn(ASTORE, cgs.objVar);

    final int tagVar = cgs.newLocal();
    decodeMessage(myFields, mv, cgs);

    cgs.pushEntity();
    mv.visitInsn(ARETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
  }

  private static void decodeMessage(final JavaColumnModel[] myFields,
      final MethodVisitor mv, final DecodeCGS cgs) throws OrmException {
    final Label nextField = new Label();
    final Label end = new Label();
    mv.visitLabel(nextField);

    // while (!ci.isAtEnd) { ...
    cgs.call("readTag", Type.INT_TYPE);
    mv.visitInsn(DUP);
    mv.visitVarInsn(ISTORE, cgs.tagVar);

    cgs.push(3);
    mv.visitInsn(IUSHR);

    final Label badField = new Label();
    final int[] caseTags = new int[1 + myFields.length];
    final Label[] caseLabels = new Label[caseTags.length];

    caseTags[0] = 0;
    caseLabels[0] = new Label();

    int gaps = 0;
    for (int i = 1; i < caseTags.length; i++) {
      caseTags[i] = myFields[i - 1].getColumnID();
      caseLabels[i] = new Label();
      gaps += caseTags[i] - (caseTags[i - 1] + 1);
    }

    if (2 * gaps / 3 <= myFields.length) {
      final int min = 0;
      final int max = caseTags[caseTags.length - 1];
      final Label[] table = new Label[max + 1];
      Arrays.fill(table, badField);
      for (int idx = 0; idx < caseTags.length; idx++) {
        table[caseTags[idx]] = caseLabels[idx];
      }
      mv.visitTableSwitchInsn(min, max, badField, table);
    } else {
      mv.visitLookupSwitchInsn(badField, caseTags, caseLabels);
    }

    mv.visitLabel(caseLabels[0]);
    mv.visitJumpInsn(GOTO, end);

    for (int idx = 1; idx < caseTags.length; idx++) {
      final JavaColumnModel f = myFields[idx - 1];
      mv.visitLabel(caseLabels[idx]);
      if (f.isNested()) {
        final Label load = new Label();
        cgs.setFieldReference(f);
        cgs.pushFieldValue();
        mv.visitJumpInsn(IFNONNULL, load);
        cgs.fieldSetBegin();
        mv.visitTypeInsn(NEW, Type.getType(f.getNestedClass())
            .getInternalName());
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, Type.getType(f.getNestedClass())
            .getInternalName(), "<init>", Type.getMethodDescriptor(
            Type.VOID_TYPE, new Type[] {}));
        cgs.fieldSetEnd();

        // read the length, set a new limit, decode the message, validate
        // we stopped at the end of it as expected.
        //
        mv.visitLabel(load);
        final int limitVar = cgs.newLocal();
        cgs.pushCodedInputStream();
        cgs.call("readRawVarint32", Type.INT_TYPE);
        cgs.ncallInt("pushLimit", Type.INT_TYPE);
        mv.visitVarInsn(ISTORE, limitVar);

        decodeMessage(sort(f.getNestedColumns()), mv, cgs);

        cgs.pushCodedInputStream();
        mv.visitVarInsn(ILOAD, limitVar);
        cgs.ncallInt("popLimit", Type.VOID_TYPE);
        cgs.freeLocal(limitVar);

      } else {
        decodeScalar(mv, cgs, f);
      }
      mv.visitJumpInsn(GOTO, nextField);
    }

    // default:
    mv.visitLabel(badField);
    cgs.pushCodedInputStream();
    mv.visitVarInsn(ILOAD, cgs.tagVar);
    cgs.ncallInt("skipField", Type.BOOLEAN_TYPE);
    mv.visitInsn(POP);
    mv.visitJumpInsn(GOTO, nextField);

    mv.visitLabel(end);
    cgs.pushCodedInputStream();
    cgs.push(0);
    cgs.ncallInt("checkLastTagWas", Type.VOID_TYPE);
  }

  private static void decodeScalar(final MethodVisitor mv, final DecodeCGS cgs,
      final JavaColumnModel f) throws OrmException {
    cgs.setFieldReference(f);
    cgs.fieldSetBegin();
    switch (Type.getType(f.getPrimitiveType()).getSort()) {
      case Type.BOOLEAN:
        cgs.call("readBool", Type.BOOLEAN_TYPE);
        break;

      case Type.CHAR:
        cgs.call("readUInt32", Type.INT_TYPE);
        break;

      case Type.BYTE:
      case Type.SHORT:
      case Type.INT:
        cgs.call("readSInt32", Type.INT_TYPE);
        break;

      case Type.FLOAT:
        cgs.call("readFloat", Type.FLOAT_TYPE);
        break;

      case Type.DOUBLE:
        cgs.call("readDouble", Type.DOUBLE_TYPE);
        break;

      case Type.LONG:
        cgs.call("readSInt64", Type.LONG_TYPE);
        break;

      default:
        if (f.getPrimitiveType() == byte[].class) {
          cgs.call("readBytes", byteString);
          mv.visitMethodInsn(INVOKEVIRTUAL, byteString.getInternalName(),
              "toByteArray", Type.getMethodDescriptor(Type
                  .getType(byte[].class), new Type[] {}));

        } else if (f.getPrimitiveType() == String.class) {
          cgs.call("readString", string);

        } else if (f.getPrimitiveType() == java.sql.Timestamp.class
            || f.getPrimitiveType() == java.util.Date.class
            || f.getPrimitiveType() == java.sql.Date.class) {
          String tsType = Type.getType(f.getPrimitiveType()).getInternalName();
          mv.visitTypeInsn(NEW, tsType);
          mv.visitInsn(DUP);
          cgs.call("readFixed64", Type.LONG_TYPE);
          mv.visitMethodInsn(INVOKESPECIAL, tsType, "<init>", Type
              .getMethodDescriptor(Type.VOID_TYPE, new Type[] {}));

        } else {
          throw new OrmException("Type " + f.getPrimitiveType()
              + " not supported for field " + f.getPathToFieldName());
        }
        break;
    }
    cgs.fieldSetEnd();
  }

  private static final class SizeofCGS extends CodeGenSupport {
    int sizeVar;

    private SizeofCGS(MethodVisitor method) {
      super(method);
      sizeVar = newLocal();
    }

    void inc(String name, Type... args) {
      mv.visitMethodInsn(INVOKESTATIC, codedOutputStream.getInternalName(),
          name, Type.getMethodDescriptor(Type.INT_TYPE, args));
      inc();
    }

    void inc() {
      mv.visitVarInsn(ILOAD, sizeVar);
      mv.visitInsn(IADD);
      mv.visitVarInsn(ISTORE, sizeVar);
    }

    @Override
    public void pushEntity() {
      mv.visitVarInsn(ALOAD, 1);
    }
  }

  private static final class EncodeCGS extends CodeGenSupport {
    int codedOutputStreamVar;

    private EncodeCGS(MethodVisitor method) {
      super(method);
    }

    void pushCodedOutputStream() {
      mv.visitVarInsn(ALOAD, codedOutputStreamVar);
    }

    void write(String name, Type arg) {
      mv.visitMethodInsn(INVOKEVIRTUAL, codedOutputStream.getInternalName(),
          name, Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {
              Type.INT_TYPE, arg}));
    }

    @Override
    public void pushEntity() {
      mv.visitVarInsn(ALOAD, 1);
    }
  }

  private static final class DecodeCGS extends CodeGenSupport {
    final int codedInputStreamVar = 1;
    final int objVar;
    final int tagVar;

    private DecodeCGS(MethodVisitor method) {
      super(method);
      objVar = newLocal();
      tagVar = newLocal();
    }

    void pushCodedInputStream() {
      mv.visitVarInsn(ALOAD, codedInputStreamVar);
    }

    void call(String name, Type ret) {
      pushCodedInputStream();
      mv.visitMethodInsn(INVOKEVIRTUAL, codedInputStream.getInternalName(),
          name, Type.getMethodDescriptor(ret, new Type[] {}));
    }

    void ncallInt(String name, Type ret) {
      mv.visitMethodInsn(INVOKEVIRTUAL, codedInputStream.getInternalName(),
          name, Type.getMethodDescriptor(ret, new Type[] {Type.INT_TYPE}));
    }

    @Override
    public void pushEntity() {
      mv.visitVarInsn(ALOAD, objVar);
    }
  }
}
