diff options
author | Shawn O. Pearce <sop@google.com> | 2010-07-28 13:01:44 -0700 |
---|---|---|
committer | Shawn O. Pearce <sop@google.com> | 2010-07-28 13:01:44 -0700 |
commit | 9a9c21d675cbb7a15ec57d8f3cf4e08ab0831949 (patch) | |
tree | 67386982696089d774f29456ceb96ef14a6f7799 | |
parent | 25732409c8808c97359de84825178a6591765a9e (diff) | |
download | gwtorm-9a9c21d675cbb7a15ec57d8f3cf4e08ab0831949.tar.gz |
protobuf: Support encoding Enums
Encode enum values using their ordinal as a varint, similar to
what the proto compiler from Google would do. This requires that
application developers carefully assign their enum orders in order
to maintain values already encoded in protobufs.
Change-Id: I1f40170c583125f425f4ff4a3aa7045ee0a820ca
Signed-off-by: Shawn O. Pearce <sop@google.com>
3 files changed, 52 insertions, 1 deletions
diff --git a/src/main/java/com/google/gwtorm/protobuf/CodecGen.java b/src/main/java/com/google/gwtorm/protobuf/CodecGen.java index a7ab7ef..5a5342b 100644 --- a/src/main/java/com/google/gwtorm/protobuf/CodecGen.java +++ b/src/main/java/com/google/gwtorm/protobuf/CodecGen.java @@ -51,6 +51,7 @@ class CodecGen<T> implements Opcodes { 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 = @@ -495,6 +496,15 @@ class CodecGen<T> implements Opcodes { .getMethodDescriptor(Type.LONG_TYPE, new Type[] {})); cgs.doinc("computeFixed64Size", Type.INT_TYPE, Type.LONG_TYPE); + } else if (f.getPrimitiveType().isEnum()) { + cgs.preinc(); + cgs.push(f.getColumnID()); + cgs.pushFieldValue(); + mv.visitMethodInsn(INVOKEVIRTUAL, enumType.getInternalName(), + "ordinal", // + Type.getMethodDescriptor(Type.INT_TYPE, new Type[] {})); + cgs.doinc("computeEnumSize", Type.INT_TYPE, Type.INT_TYPE); + } else { throw new OrmException("Type " + f.getPrimitiveType() + " not supported for field " + f.getPathToFieldName()); @@ -764,6 +774,12 @@ class CodecGen<T> implements Opcodes { .getMethodDescriptor(Type.LONG_TYPE, new Type[] {})); cgs.write("writeFixed64", Type.LONG_TYPE); + } else if (f.getPrimitiveType().isEnum()) { + mv.visitMethodInsn(INVOKEVIRTUAL, enumType.getInternalName(), + "ordinal", // + Type.getMethodDescriptor(Type.INT_TYPE, new Type[] {})); + cgs.write("writeEnum", Type.INT_TYPE); + } else { throw new OrmException("Type " + f.getPrimitiveType() + " not supported for field " + f.getPathToFieldName()); @@ -1128,6 +1144,14 @@ class CodecGen<T> implements Opcodes { Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {Type.LONG_TYPE})); + } else if (f.getPrimitiveType().isEnum()) { + Type et = Type.getType(f.getPrimitiveType()); + mv.visitMethodInsn(INVOKESTATIC, et.getInternalName(), "values", Type + .getMethodDescriptor(Type.getType("[" + et.getDescriptor()), + new Type[] {})); + cgs.call("readEnum", Type.INT_TYPE); + mv.visitInsn(AALOAD); + } else { throw new OrmException("Type " + f.getPrimitiveType() + " not supported for field " + f.getPathToFieldName()); diff --git a/src/main/java/com/google/gwtorm/schema/Util.java b/src/main/java/com/google/gwtorm/schema/Util.java index ff34f0a..1ca5e5d 100644 --- a/src/main/java/com/google/gwtorm/schema/Util.java +++ b/src/main/java/com/google/gwtorm/schema/Util.java @@ -67,7 +67,7 @@ public class Util { if (type == null || type == Void.TYPE) { return false; } - if (type.isPrimitive()) { + if (type.isPrimitive() || type.isEnum()) { return true; } if (type == String.class) { diff --git a/src/test/java/com/google/gwtorm/protobuf/ProtobufEncoderTest.java b/src/test/java/com/google/gwtorm/protobuf/ProtobufEncoderTest.java index 14544c0..21007f6 100644 --- a/src/test/java/com/google/gwtorm/protobuf/ProtobufEncoderTest.java +++ b/src/test/java/com/google/gwtorm/protobuf/ProtobufEncoderTest.java @@ -197,6 +197,24 @@ public class ProtobufEncoderTest extends TestCase { assertEquals(2, other.list.size()); } + public void testEnumEncoder() throws UnsupportedEncodingException { + assertEquals(1, ThingWithEnum.Type.B.ordinal()); + assertSame(ThingWithEnum.Type.B, ThingWithEnum.Type.values()[1]); + + ProtobufCodec<ThingWithEnum> e = CodecFactory.encoder(ThingWithEnum.class); + + ThingWithEnum thing = new ThingWithEnum(); + thing.type = ThingWithEnum.Type.B; + + ThingWithEnum other = e.decode(e.encodeToByteArray(thing)); + assertNotNull(other.type); + assertSame(thing.type, other.type); + + byte[] act = e.encodeToByteArray(thing); + byte[] exp = {0x08, 0x01}; + assertEquals(asString(exp), asString(act)); + } + private static String asString(byte[] bin) throws UnsupportedEncodingException { return new String(bin, "ISO-8859-1"); @@ -247,4 +265,13 @@ public class ProtobufEncoderTest extends TestCase { @CustomCodec(ItemCodec.class) List<Item> list; } + + static class ThingWithEnum { + static enum Type { + A, B; + } + + @Column(id = 1) + Type type; + } } |