diff options
author | Ulas Kirazci <ulas@google.com> | 2013-10-09 17:51:07 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2013-10-09 17:51:07 +0000 |
commit | 2b51f83a83f2ba8d3730d90ec0a7997f59f30931 (patch) | |
tree | 659637fad12b8ac790ef2fd7b1fe0de01b354d2f /java | |
parent | 1410c721d9c7ffa6b2e59524b55ae6498f8de8b9 (diff) | |
parent | 10107cbc7a0159afce57795863c140e1622c9688 (diff) | |
download | protobuf-2b51f83a83f2ba8d3730d90ec0a7997f59f30931.tar.gz protobuf-2b51f83a83f2ba8d3730d90ec0a7997f59f30931.tar.bz2 protobuf-2b51f83a83f2ba8d3730d90ec0a7997f59f30931.zip |
Merge "Add reftypes field generator option."
Diffstat (limited to 'java')
-rw-r--r-- | java/README.txt | 71 | ||||
-rw-r--r-- | java/src/test/java/com/google/protobuf/NanoTest.java | 62 |
2 files changed, 114 insertions, 19 deletions
diff --git a/java/README.txt b/java/README.txt index e2e698e1..adc1972c 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/src/test/java/com/google/protobuf/NanoTest.java b/java/src/test/java/com/google/protobuf/NanoTest.java index ca0bcda4..4f2ac3f8 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); |