diff options
author | Brian Duff <bduff@google.com> | 2013-09-30 20:49:13 -0700 |
---|---|---|
committer | Brian Duff <bduff@google.com> | 2013-10-07 16:25:55 -0700 |
commit | 0b8579237336f221711a0aac42400eb31a58fed3 (patch) | |
tree | ac6553ae2998404642d43dfacd5d56a1a03412bf /java | |
parent | 9827c718c45cfa1744a3b0f8fc27dac9cd415603 (diff) | |
download | external_protobuf-0b8579237336f221711a0aac42400eb31a58fed3.zip external_protobuf-0b8579237336f221711a0aac42400eb31a58fed3.tar.gz external_protobuf-0b8579237336f221711a0aac42400eb31a58fed3.tar.bz2 |
Add reftypes field generator option.
This option generates fields as reference types, and serializes
based on nullness.
Change-Id: Ic32e0eebff59d14016cc9a19e15a9bb08ae0bba5
Signed-off-by: Brian Duff <bduff@google.com>
Diffstat (limited to 'java')
-rw-r--r-- | java/README.txt | 71 | ||||
-rw-r--r-- | java/pom.xml | 6 | ||||
-rw-r--r-- | java/src/test/java/com/google/protobuf/NanoTest.java | 62 |
3 files changed, 120 insertions, 19 deletions
diff --git a/java/README.txt b/java/README.txt index e2e698e..adc1972 100644 --- a/java/README.txt +++ b/java/README.txt @@ -487,34 +487,67 @@ java_nano_generate_has={true,false} (default: false) many cases reading the default works and determining whether the field was received over the wire is irrelevant. -optional_field_style={default,accessors} (default: default) - Defines the style of the generated code for _optional_ fields only. +optional_field_style={default,accessors,reftypes} (default: default) + Defines the style of the generated code for fields. + + * default * + In the default style, optional fields translate into public mutable Java fields, and the serialization process is as discussed in the - "IMPORTANT" section above. When set to 'accessors', each optional - field is encapsulated behind 4 accessors, namely get<fieldname>(), - set<fieldname>(), has<fieldname>() and clear<fieldname>() methods, - with the standard semantics. The hazzer's return value determines - whether a field is serialized, so this style is useful when you need - to serialize a field with the default value, or check if a field has - been explicitly set to its default value from the wire. - - Required fields are still translated to one public mutable Java - field each, and repeated fields are still translated to arrays. No - accessors are generated for them. - - optional_field_style=accessors cannot be used together with - java_nano_generate_has=true. If you need the 'has' flag for any - required field (you have no reason to), you can only use - java_nano_generate_has=true. + "IMPORTANT" section above. - IMPORTANT: When using the 'accessor' style, ProGuard should always + * accessors * + + When set to 'accessors', each optional field is encapsulated behind + 4 accessors, namely get<fieldname>(), set<fieldname>(), has<fieldname>() + and clear<fieldname>() methods, with the standard semantics. The hazzer's + return value determines whether a field is serialized, so this style is + useful when you need to serialize a field with the default value, or check + if a field has been explicitly set to its default value from the wire. + + In the 'accessors' style, required fields are still translated to one + public mutable Java field each, and repeated fields are still translated + to arrays. No accessors are generated for them. + + IMPORTANT: When using the 'accessors' style, ProGuard should always be enabled with optimization (don't use -dontoptimize) and allowing access modification (use -allowaccessmodification). This removes the unused accessors and maybe inline the rest at the call sites, reducing the final code size. TODO(maxtroy): find ProGuard config that would work the best. + * reftypes * + + When set to 'reftypes', each proto field is generated as a public Java + field. For primitive types, these fields use the Java reference types + such as java.lang.Integer instead of primitive types such as int. + + In the 'reftypes' style, fields are initialized to null (or empty + arrays for repeated fields), and their default values are not available. + They are serialized over the wire based on equality to null. + + The 'reftypes' mode has some additional cost due to autoboxing and usage + of reference types. In practice, many boxed types are cached, and so don't + result in object creation. However, references do take slightly more memory + than primitives. + + The 'reftypes' mode is useful when you want to be able to serialize fields + with default values, or check if a field has been explicitly set to the + default over the wire without paying the extra method cost of the + 'accessors' mode. + + Note that if you attempt to write null to a required field in the reftypes + mode, serialization of the proto will cause a NullPointerException. This is + an intentional indicator that you must set required fields. + + + NOTE + optional_field_style=accessors or reftypes cannot be used together with + java_nano_generate_has=true. If you need the 'has' flag for any + required field (you have no reason to), you can only use + java_nano_generate_has=true. + + To use nano protobufs: - Link with the generated jar file diff --git a/java/pom.xml b/java/pom.xml index a34c164..1f43670 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -171,6 +171,12 @@ <arg value="../src/google/protobuf/unittest_enum_class_nano.proto" /> <arg value="../src/google/protobuf/unittest_enum_class_multiple_nano.proto" /> </exec> + <exec executable="../src/protoc"> + <arg value="--javanano_out=optional_field_style=reftypes:target/generated-test-sources" /> + <arg value="--proto_path=../src" /> + <arg value="--proto_path=src/test/java" /> + <arg value="../src/google/protobuf/unittest_reference_types_nano.proto" /> + </exec> </tasks> <testSourceRoot>target/generated-test-sources</testSourceRoot> <!--testSourceRoot>target/generated-test-sources/opt-space</testSourceRoot--> diff --git a/java/src/test/java/com/google/protobuf/NanoTest.java b/java/src/test/java/com/google/protobuf/NanoTest.java index ca0bcda..4f2ac3f 100644 --- a/java/src/test/java/com/google/protobuf/NanoTest.java +++ b/java/src/test/java/com/google/protobuf/NanoTest.java @@ -48,6 +48,7 @@ import com.google.protobuf.nano.NanoAccessorsOuterClass.TestNanoAccessors; import com.google.protobuf.nano.NanoHasOuterClass.TestAllTypesNanoHas; import com.google.protobuf.nano.NanoOuterClass; import com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano; +import com.google.protobuf.nano.NanoReferenceTypes; import com.google.protobuf.nano.UnittestImportNano; import com.google.protobuf.nano.UnittestMultipleNano; import com.google.protobuf.nano.UnittestRecursiveNano.RecursiveMessageNano; @@ -2624,6 +2625,67 @@ public class NanoTest extends TestCase { assertEquals(123, msg.synchronized_); } + public void testReferenceTypesForPrimitives() throws Exception { + NanoReferenceTypes.TestAllTypesNano message = new NanoReferenceTypes.TestAllTypesNano(); + + // Base check - when nothing is set, we serialize nothing. + assertHasWireData(message, false); + + message.defaultBool = true; + assertHasWireData(message, true); + + message.defaultBool = false; + assertHasWireData(message, true); + + message.defaultBool = null; + assertHasWireData(message, false); + + message.defaultInt32 = 5; + assertHasWireData(message, true); + + message.defaultInt32 = null; + assertHasWireData(message, false); + + message.defaultInt64 = 123456L; + assertHasWireData(message, true); + + message.defaultInt64 = null; + assertHasWireData(message, false); + + message.defaultFloat = 1f; + assertHasWireData(message, true); + + message.defaultFloat = null; + assertHasWireData(message, false); + + message.defaultDouble = 2.1; + assertHasWireData(message, true); + + message.defaultDouble = null; + assertHasWireData(message, false); + + message.defaultString = "hello"; + assertHasWireData(message, true); + + message.defaultString = null; + assertHasWireData(message, false); + + message.defaultBytes = new byte[] { 1, 2, 3 }; + assertHasWireData(message, true); + + message.defaultBytes = null; + assertHasWireData(message, false); + } + + private void assertHasWireData(MessageNano message, boolean expected) { + int wireLength = MessageNano.toByteArray(message).length; + if (expected) { + assertFalse(wireLength == 0); + } else { + assertEquals(0, wireLength); + } + } + private <T> List<T> list(T first, T... remaining) { List<T> list = new ArrayList<T>(); list.add(first); |