Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   // 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 java.util.Arrays;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Map;
  import java.util.TreeSet;

Generates ProtobufCodec implementations.
  
  class CodecGen<T> implements Opcodes {
    private static final Type illegalStateException =
        Type.getType(IllegalStateException.class);
    private static final Type collection =
        Type.getType(java.util.Collection.class);
    private static final Type iterator = Type.getType(java.util.Iterator.class);
    private static final Type string = Type.getType(String.class);
    private static final Type enumType = Type.getType(Enum.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;
  
    private Map<Class<?>, NestedCodecnestedCodecs;
  
    public CodecGen(final GeneratedClassLoader loaderfinal Class<T> t) {
       = loader;
       = t;
       = Type.getType();
       = new HashMap<Class<?>, NestedCodec>();
    }
  
    public ProtobufCodec<T> create() throws OrmException {
       = scanFields();
  
      init();
  
      implementSizeofSelf();
  
      implementEncodeSelf();
  
  
      implementCodecFields();
      implementStaticInit();
      implementConstructor();
      .visitEnd();
 
     try {
       final Class<?> c = Class.forName(true);
       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<?> inthrows OrmException {
     final Collection<JavaColumnModelcol = new ArrayList<JavaColumnModel>();
     while (in != null) {
       for (final Field f : JavaColumnModel.getDeclaredFields(in)) {
         if (f.getAnnotation(Column.class) != null) {
           col.add(new JavaColumnModel(f));
         }
       }
       in = in.getSuperclass();
     }
     if (col.isEmpty()) {
       throw new OrmException(
           "Cannot create new encoder, no @Column fields found");
     }
     return sort(col);
   }
 
   private static JavaColumnModel[] sort(
       final Collection<? extends ColumnModelcol) {
     JavaColumnModel[] out = col.toArray(new JavaColumnModel[col.size()]);
     Arrays.sort(outnew Comparator<JavaColumnModel>() {
       @Override
       public int compare(JavaColumnModel o1JavaColumnModel 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() {
      = .getName() + "_protobuf_" + Util.createRandomName();
      = .replace('.''/');
 
     .visit( |  | null,
         new String[] {});
   }
 
   private void implementCodecFields() {
     for (NestedCodec other : .values()) {
       .visitField( |  | other.field,
           other.codecType.getDescriptor(), nullnull).visitEnd();
     }
   }
 
   private void implementStaticInit() {
     final MethodVisitor mv =
         .visitMethod( | "<clinit>", Type
             .getMethodDescriptor(.new Type[] {}), nullnull);
     mv.visitCode();
 
     for (NestedCodec other : .values()) {
       mv.visitTypeInsn(other.codecType.getInternalName());
       mv.visitInsn();
       mv.visitMethodInsn(other.codecType.getInternalName(),
           "<init>", Type.getMethodDescriptor(.new Type[] {}));
       mv.visitFieldInsn(other.fieldother.codecType
           .getDescriptor());
     }
 
     mv.visitInsn();
     mv.visitMaxs(-1, -1);
     mv.visitEnd();
   }
 
   private void implementConstructor() {
     final String consName = "<init>";
     final String consDesc =
         Type.getMethodDescriptor(.new Type[] {});
     final MethodVisitor mv =
         .visitMethod(consNameconsDescnullnull);
     mv.visitCode();
 
     mv.visitVarInsn(, 0);
     mv.visitMethodInsn(consNameconsDesc);
 
     mv.visitInsn();
     mv.visitMaxs(-1, -1);
     mv.visitEnd();
   }
 
   private void implementNewInstanceObject() {
     final MethodVisitor mv =
         .visitMethod("newInstance", Type.getMethodDescriptor(
             new Type[] {}), nullnew String[] {});
     mv.visitCode();
 
     mv.visitInsn();
         Type.getMethodDescriptor(.new Type[] {}));
 
     mv.visitInsn();
     mv.visitMaxs(-1, -1);
     mv.visitEnd();
   }
 
   private void implementNewInstanceSelf() {
     final MethodVisitor mv =
         .visitMethod("newInstance", Type.getMethodDescriptor(
             new Type[] {}), nullnew String[] {});
     mv.visitCode();
 
     mv.visitInsn();
         Type.getMethodDescriptor(.new Type[] {}));
 
     mv.visitInsn();
     mv.visitMaxs(-1, -1);
     mv.visitEnd();
   }
 
   private void implementSizeofObject() {
     final MethodVisitor mv =
         .visitMethod("sizeof", Type.getMethodDescriptor(
             .new Type[] {}), nullnew String[] {});
     mv.visitCode();
     final SizeofCGS cgs = new SizeofCGS(mv);
     cgs.sizeVar = cgs.newLocal();
     cgs.setEntityType();
 
     mv.visitVarInsn(, 0);
     mv.visitVarInsn(, 1);
     mv.visitMethodInsn("sizeof", Type
         .getMethodDescriptor(.new Type[] {}));
 
     mv.visitInsn();
     mv.visitMaxs(-1, -1);
     mv.visitEnd();
   }
 
   private void implementSizeofSelf() throws OrmException {
     final MethodVisitor mv =
         .visitMethod("sizeof", Type.getMethodDescriptor(
             .new Type[] {}), nullnew String[] {});
     mv.visitCode();
     final SizeofCGS cgs = new SizeofCGS(mv);
     cgs.sizeVar = cgs.newLocal();
     cgs.setEntityType();
 
     cgs.push(0);
     mv.visitVarInsn(cgs.sizeVar);
     sizeofMessage(mvcgs);
 
     mv.visitVarInsn(cgs.sizeVar);
     mv.visitInsn();
     mv.visitMaxs(-1, -1);
     mv.visitEnd();
   }
 
   private void sizeofMessage(final JavaColumnModel[] myFields,
       final MethodVisitor mvfinal SizeofCGS cgsthrows OrmException {
     for (final JavaColumnModel f : myFields) {
       if (f.isNested()) {
         final NestedCodec n = nestedFor(f);
         final Label end = new Label();
         cgs.setFieldReference(f);
         cgs.pushFieldValue();
         mv.visitJumpInsn(end);
 
         final int msgSizeVar = cgs.newLocal();
         mv.visitFieldInsn(n.fieldn.codecType
             .getDescriptor());
         cgs.pushFieldValue();
         mv.visitMethodInsn(n.codecType.getInternalName(),
             "sizeof", Type.getMethodDescriptor(.,
                 new Type[] {n.pojoType}));
         mv.visitVarInsn(msgSizeVar);
 
         cgs.preinc();
         cgs.push(f.getColumnID());
         cgs.doinc("computeTagSize".);
 
         cgs.preinc();
         mv.visitVarInsn(msgSizeVar);
         cgs.doinc("computeRawVarint32Size".);
 
         cgs.preinc();
         mv.visitVarInsn(msgSizeVar);
         cgs.doinc();
 
         cgs.freeLocal(msgSizeVar);
         mv.visitLabel(end);
 
       } else if (f.isCollection()) {
         sizeofCollection(fmvcgs);
 
       } else {
         sizeofScalar(mvcgsf);
       }
     }
   }
 
   @SuppressWarnings({"unchecked""rawtypes"})
     Class clazz = f.getNestedClass();
     NestedCodec n = .get(clazz);
     if (n == null) {
       Class<? extends ProtobufCodeccodec = null;
       Type type = Type.getType(clazz);
       if (f.getField() != null) {
         final CustomCodec cc = f.getField().getAnnotation(CustomCodec.class);
         if (cc != null) {
           codec = cc.value();
           type = ;
         }
       }
       if (codec == null) {
         codec = CodecFactory.encoder(clazz).getClass();
       }
 
       n = new NestedCodec("codec" + f.getColumnID(), codectype);
       .put(clazzn);
     }
     return n;
   }
 
   private void sizeofCollection(final JavaColumnModel f,
       final MethodVisitor mvfinal SizeofCGS cgsthrows OrmException {
     final int itr = cgs.newLocal();
     final int val = cgs.newLocal();
     final Class<?> valClazz = (Class<?>) f.getArgumentTypes()[0];
     final Type valType = Type.getType(valClazz);
     final JavaColumnModel col = collectionColumn(fvalClazz);
     final SizeofCGS ng = new SizeofCGS(mv) {
       {
          = cgs.sizeVar;
         setEntityType(valType);
       }
 
       @Override
       public void pushEntity() {
         .visitVarInsn(val);
       }
 
       @Override
       protected void appendGetField(final ColumnModel c) {
         if (c != col) {
           super.appendGetField(c);
         }
       }
 
       @Override
       public int newLocal() {
         return cgs.newLocal();
       }
 
       @Override
       public void freeLocal(int index) {
         cgs.freeLocal(index);
       }
     };
 
     final Label end = new Label();
     cgs.setFieldReference(f);
     cgs.pushFieldValue();
     mv.visitJumpInsn(end);
 
     cgs.setFieldReference(f);
     cgs.pushFieldValue();
         "iterator", Type.getMethodDescriptor(new Type[] {}));
     mv.visitVarInsn(itr);
 
     final Label doloop = new Label();
     mv.visitLabel(doloop);
     mv.visitVarInsn(itr);
         Type.getMethodDescriptor(.new Type[] {}));
     mv.visitJumpInsn(end);
 
     mv.visitVarInsn(itr);
         Type.getMethodDescriptor(new Type[] {}));
     mv.visitTypeInsn(valType.getInternalName());
     mv.visitVarInsn(val);
 
     sizeofMessage(new JavaColumnModel[] {col}, mvng);
     mv.visitJumpInsn(doloop);
 
     mv.visitLabel(end);
     cgs.freeLocal(itr);
     cgs.freeLocal(val);
   }
 
       final Class<?> valClazzthrows OrmException {
     return new JavaColumnModel//
         f.getField(), //
         f.getPathToFieldName(), //
         f.getColumnID(), //
         valClazz);
   }
 
   private void sizeofScalar(final MethodVisitor mvfinal SizeofCGS cgs,
       final JavaColumnModel fthrows OrmException {
     cgs.setFieldReference(f);
 
     switch (Type.getType(f.getPrimitiveType()).getSort()) {
       case .:
         cgs.preinc();
         cgs.push(f.getColumnID());
         cgs.pushFieldValue();
         cgs.doinc("computeBoolSize"..);
         break;
 
       case .:
         cgs.preinc();
         cgs.push(f.getColumnID());
         cgs.pushFieldValue();
         cgs.doinc("computeUInt32Size"..);
         break;
 
       case .:
       case .:
       case .:
         cgs.preinc();
         cgs.push(f.getColumnID());
         cgs.pushFieldValue();
         cgs.doinc("computeInt32Size"..);
         break;
 
       case .:
         cgs.preinc();
         cgs.push(f.getColumnID());
         cgs.pushFieldValue();
         cgs.doinc("computeFloatSize"..);
         break;
 
       case .:
         cgs.preinc();
         cgs.push(f.getColumnID());
         cgs.pushFieldValue();
         cgs.doinc("computeDoubleSize"..);
         break;
 
       case .:
         cgs.preinc();
         cgs.push(f.getColumnID());
         cgs.pushFieldValue();
         cgs.doinc("computeInt64Size"..);
         break;
 
       case .:
       case .: {
         final Label end = new Label();
         cgs.pushFieldValue();
         mv.visitJumpInsn(end);
 
         if (f.getPrimitiveType() == byte[].class) {
           cgs.preinc();
           cgs.push(f.getColumnID());
           cgs.doinc("computeTagSize".);
 
           cgs.preinc();
           cgs.pushFieldValue();
           mv.visitInsn();
           cgs.doinc("computeRawVarint32Size".);
 
           cgs.preinc();
           cgs.pushFieldValue();
           mv.visitInsn();
           cgs.doinc();
 
         } else if (f.getPrimitiveType() == String.class) {
           cgs.preinc();
           cgs.push(f.getColumnID());
           cgs.pushFieldValue();
           cgs.doinc("computeStringSize".);
 
         } else if (f.getPrimitiveType() == java.sql.Timestamp.class
             || f.getPrimitiveType() == java.util.Date.class
             || f.getPrimitiveType() == java.sql.Date.class) {
           cgs.preinc();
           cgs.push(f.getColumnID());
           cgs.pushFieldValue();
           String tsType = Type.getType(f.getPrimitiveType()).getInternalName();
           mv.visitMethodInsn(tsType"getTime", Type
               .getMethodDescriptor(.new Type[] {}));
           cgs.doinc("computeFixed64Size"..);
 
         } else if (f.getPrimitiveType().isEnum()) {
           cgs.preinc();
           cgs.push(f.getColumnID());
           cgs.pushFieldValue();
               "ordinal"//
               Type.getMethodDescriptor(.new Type[] {}));
           cgs.doinc("computeEnumSize"..);
 
         } 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 implementEncodeObject() {
     final MethodVisitor mv =
         .visitMethod("encode", Type.getMethodDescriptor(
             .new Type[] {}), null,
             new String[] {});
     mv.visitCode();
     final EncodeCGS cgs = new EncodeCGS(mv);
     cgs.setEntityType();
 
     mv.visitVarInsn(, 0);
     mv.visitVarInsn(, 1);
     mv.visitVarInsn(, 2);
     mv.visitMethodInsn("encode", Type
         .getMethodDescriptor(.new Type[] {,
             }));
 
     mv.visitInsn();
     mv.visitMaxs(-1, -1);
     mv.visitEnd();
   }
 
   private void implementEncodeSelf() throws OrmException {
     final MethodVisitor mv =
         .visitMethod("encode", Type.getMethodDescriptor(
             .new Type[] {}), null,
             new String[] {});
     mv.visitCode();
     final EncodeCGS cgs = new EncodeCGS(mv);
     cgs.setEntityType();
 
     encodeMessage(mvcgs);
 
     mv.visitInsn();
     mv.visitMaxs(-1, -1);
     mv.visitEnd();
   }
 
   private void encodeMessage(final JavaColumnModel[] myFields,
       final MethodVisitor mvfinal EncodeCGS cgsthrows OrmException {
     for (final JavaColumnModel f : myFields) {
       if (f.isNested()) {
         final NestedCodec n = nestedFor(f);
 
         final Label end = new Label();
         cgs.setFieldReference(f);
         cgs.pushFieldValue();
         mv.visitJumpInsn(end);
 
         final int msgSizeVar = cgs.newLocal();
         mv.visitFieldInsn(n.fieldn.codecType
             .getDescriptor());
         cgs.pushFieldValue();
         mv.visitMethodInsn(n.codecType.getInternalName(),
             "sizeof", Type.getMethodDescriptor(.,
                 new Type[] {n.pojoType}));
         mv.visitVarInsn(msgSizeVar);
 
         cgs.pushCodedOutputStream();
         cgs.push(f.getColumnID());
         cgs.push(...getWireType());
             "writeTag", Type.getMethodDescriptor(.new Type[] {
                 ..}));
 
         cgs.pushCodedOutputStream();
         mv.visitVarInsn(msgSizeVar);
             "writeRawVarint32", Type.getMethodDescriptor(.,
                 new Type[] {.}));
 
         mv.visitFieldInsn(n.fieldn.codecType
             .getDescriptor());
         cgs.pushFieldValue();
         cgs.pushCodedOutputStream();
         mv.visitMethodInsn(n.codecType.getInternalName(),
             "encode", Type.getMethodDescriptor(.new Type[] {
                 n.pojoType}));
 
         cgs.freeLocal(msgSizeVar);
         mv.visitLabel(end);
 
       } else if (f.isCollection()) {
         encodeCollection(fmvcgs);
 
       } else {
         encodeScalar(mvcgsf);
       }
     }
   }
 
   private void encodeCollection(final JavaColumnModel f,
       final MethodVisitor mvfinal EncodeCGS cgsthrows OrmException {
     final int itr = cgs.newLocal();
     final int val = cgs.newLocal();
     final Class<?> valClazz = (Class<?>) f.getArgumentTypes()[0];
     final Type valType = Type.getType(valClazz);
     final JavaColumnModel col = collectionColumn(fvalClazz);
     final EncodeCGS ng = new EncodeCGS(mv) {
       {
          = cgs.sizeVar;
         setEntityType(valType);
       }
 
       @Override
       public void pushEntity() {
         .visitVarInsn(val);
       }
 
       @Override
       protected void appendGetField(final ColumnModel c) {
         if (c != col) {
           super.appendGetField(c);
         }
       }
 
       @Override
       public int newLocal() {
         return cgs.newLocal();
       }
 
       @Override
       public void freeLocal(int index) {
         cgs.freeLocal(index);
       }
     };
 
     final Label end = new Label();
     cgs.setFieldReference(f);
     cgs.pushFieldValue();
     mv.visitJumpInsn(end);
 
     cgs.setFieldReference(f);
     cgs.pushFieldValue();
         "iterator", Type.getMethodDescriptor(new Type[] {}));
     mv.visitVarInsn(itr);
 
     final Label doloop = new Label();
     mv.visitLabel(doloop);
     mv.visitVarInsn(itr);
         Type.getMethodDescriptor(.new Type[] {}));
     mv.visitJumpInsn(end);
 
     mv.visitVarInsn(itr);
         Type.getMethodDescriptor(new Type[] {}));
     mv.visitTypeInsn(valType.getInternalName());
     mv.visitVarInsn(val);
 
     encodeMessage(new JavaColumnModel[] {col}, mvng);
     mv.visitJumpInsn(doloop);
 
     mv.visitLabel(end);
     cgs.freeLocal(itr);
     cgs.freeLocal(val);
   }
 
   private void encodeScalar(final MethodVisitor mvfinal EncodeCGS cgs,
       final JavaColumnModel fthrows OrmException {
     cgs.setFieldReference(f);
 
     switch (Type.getType(f.getPrimitiveType()).getSort()) {
       case .:
         cgs.pushCodedOutputStream();
         cgs.push(f.getColumnID());
         cgs.pushFieldValue();
         cgs.write("writeBool".);
         break;
 
       case .:
         cgs.pushCodedOutputStream();
         cgs.push(f.getColumnID());
         cgs.pushFieldValue();
         cgs.write("writeUInt32".);
         break;
 
       case .:
       case .:
       case .:
         cgs.pushCodedOutputStream();
         cgs.push(f.getColumnID());
         cgs.pushFieldValue();
         cgs.write("writeInt32".);
         break;
 
       case .:
         cgs.pushCodedOutputStream();
         cgs.push(f.getColumnID());
         cgs.pushFieldValue();
         cgs.write("writeFloat".);
         break;
 
       case .:
         cgs.pushCodedOutputStream();
         cgs.push(f.getColumnID());
         cgs.pushFieldValue();
         cgs.write("writeDouble".);
         break;
 
       case .:
         cgs.pushCodedOutputStream();
         cgs.push(f.getColumnID());
         cgs.pushFieldValue();
         cgs.write("writeInt64".);
         break;
 
       case .:
       case .: {
         final Label end = new Label();
         cgs.pushFieldValue();
         mv.visitJumpInsn(end);
 
         if (f.getPrimitiveType() == byte[].class) {
           cgs.pushCodedOutputStream();
           cgs.push(f.getColumnID());
           cgs.push(...getWireType());
           mv.visitMethodInsn(,
               .getInternalName(), "writeTag", Type
                   .getMethodDescriptor(.new Type[] {
                       ..}));
 
           cgs.pushCodedOutputStream();
           cgs.pushFieldValue();
           mv.visitInsn();
           mv.visitMethodInsn(,
               .getInternalName(), "writeRawVarint32", Type
                   .getMethodDescriptor(.,
                       new Type[] {.}));
 
           cgs.pushCodedOutputStream();
           cgs.pushFieldValue();
           mv.visitMethodInsn(,
               .getInternalName(), "writeRawBytes", Type
                   .getMethodDescriptor(.new Type[] {Type
                       .getType(byte[].class)}));
 
         } else {
           cgs.pushCodedOutputStream();
           cgs.push(f.getColumnID());
           cgs.pushFieldValue();
 
           if (f.getPrimitiveType() == String.class) {
             cgs.write("writeString");
 
           } 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(tsType"getTime", Type
                 .getMethodDescriptor(.new Type[] {}));
             cgs.write("writeFixed64".);
 
           } else if (f.getPrimitiveType().isEnum()) {
             mv.visitMethodInsn(.getInternalName(),
                 "ordinal"//
                 Type.getMethodDescriptor(.new Type[] {}));
             cgs.write("writeEnum".);
 
           } 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 implementMergeFromObject() {
     final MethodVisitor mv =
         .visitMethod("mergeFrom", Type.getMethodDescriptor(
             .new Type[] {}), null,
             new String[] {});
     mv.visitCode();
 
     mv.visitVarInsn(, 0);
     mv.visitVarInsn(, 1);
     mv.visitVarInsn(, 2);
     mv.visitMethodInsn("mergeFrom", Type
             }));
 
     mv.visitInsn();
     mv.visitMaxs(-1, -1);
     mv.visitEnd();
   }
 
   private void implementMergeFromSelf() throws OrmException {
     final MethodVisitor mv =
         .visitMethod("mergeFrom", Type.getMethodDescriptor(
             .new Type[] {}), null,
             new String[] {});
     mv.visitCode();
     final DecodeCGS cgs = new DecodeCGS(mv);
     cgs.objVar = 2;
     cgs.tagVar = cgs.newLocal();
     cgs.setEntityType();
 
     decodeMessage(mvcgs);
 
     mv.visitInsn();
     mv.visitMaxs(-1, -1);
     mv.visitEnd();
   }
 
   private void decodeMessage(final JavaColumnModel[] myFields,
       final MethodVisitor mvfinal DecodeCGS cgsthrows OrmException {
     final Label nextField = new Label();
     final Label end = new Label();
     mv.visitLabel(nextField);
 
     // while (!ci.isAtEnd) { ...
     cgs.call("readTag".);
     mv.visitInsn();
     mv.visitVarInsn(cgs.tagVar);
 
     cgs.push(3);
     mv.visitInsn();
 
     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.lengthi++) {
       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(tablebadField);
       for (int idx = 0; idx < caseTags.lengthidx++) {
         table[caseTags[idx]] = caseLabels[idx];
       }
       mv.visitTableSwitchInsn(minmaxbadFieldtable);
     } else {
       mv.visitLookupSwitchInsn(badFieldcaseTagscaseLabels);
     }
 
     mv.visitLabel(caseLabels[0]);
     mv.visitJumpInsn(end);
 
     for (int idx = 1; idx < caseTags.lengthidx++) {
       final JavaColumnModel f = myFields[idx - 1];
       mv.visitLabel(caseLabels[idx]);
       decodeField(mvcgsf);
       mv.visitJumpInsn(nextField);
     }
 
     // default:
     mv.visitLabel(badField);
     cgs.pushCodedInputStream();
     mv.visitVarInsn(cgs.tagVar);
     cgs.ncallInt("skipField".);
     mv.visitInsn();
     mv.visitJumpInsn(nextField);
 
     mv.visitLabel(end);
     cgs.pushCodedInputStream();
     cgs.push(0);
     cgs.ncallInt("checkLastTagWas".);
   }
 
   private void decodeField(final MethodVisitor mvfinal DecodeCGS cgs,
       final JavaColumnModel fthrows OrmException {
     if (f.isNested()) {
       final NestedCodec n = nestedFor(f);
       final Label load = new Label();
       cgs.setFieldReference(f);
       cgs.pushFieldValue();
       mv.visitJumpInsn(load);
 
       // Since the field isn't initialized, construct it
       //
       cgs.fieldSetBegin();
       mv.visitFieldInsn(n.fieldn.codecType
           .getDescriptor());
       mv.visitMethodInsn(n.codecType.getInternalName(),
           "newInstance", Type.getMethodDescriptor(n.pojoTypenew Type[] {}));
       if (.equals(n.pojoType)) {
         mv.visitTypeInsn(, Type.getType(f.getNestedClass())
             .getInternalName());
       }
       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".);
       cgs.ncallInt("pushLimit".);
       mv.visitVarInsn(limitVar);
 
       mv.visitFieldInsn(n.fieldn.codecType
           .getDescriptor());
       cgs.pushCodedInputStream();
       cgs.pushFieldValue();
       mv.visitMethodInsn(n.codecType.getInternalName(),
           "mergeFrom", Type.getMethodDescriptor(.new Type[] {
               n.pojoType}));
 
       cgs.pushCodedInputStream();
       mv.visitVarInsn(limitVar);
       cgs.ncallInt("popLimit".);
       cgs.freeLocal(limitVar);
 
     } else if (f.isCollection()) {
       decodeCollection(mvcgsf);
 
     } else {
       decodeScalar(mvcgsf);
     }