You're right, we might as well always call it. On Wed, Nov 25, 2009 at 9:08 AM, <jas...@google.com> wrote:
> Done. But it occurs to me that this isn't all that much nicer a solution > than just calling getSerializedSize() in writeTo(CodedOutputStream > output), except that it only happens for messages with packed fields, > rather than all messages. Should this compute only the serialized size > of the packed field, so that it doesn't needlessly compute the size of > all the unpacked fields? Or does this not really matter? I think all of > the wrappers now call getSerializedSize() thanks to r240 (I was tearing > my hair out trying to figure out why I could not get a new test which > just did > ByteArrayOutputStream output = new ByteArrayOutputStream(); > message.writeTo(output); > would not fail from the open source code, but would if I added the same > test to our internal version, until I finally looked at the source). > Anyway point being that in most cases getSerializedSize() will have > already been called anyway so maybe it doesn't matter too much if we > compute the size of the entire message rather than just the packed > fields. > > > On 2009/11/25 03:42:18, kenton wrote: > >> On Tue, Nov 24, 2009 at 7:40 PM, Kenton Varda >> > <mailto:ken...@google.com> wrote: > > > I guess it's technically the case that a packed field always has >> > non-zero > >> > size, but maybe we should initialize the cached sizes to -1 anyway >> > to make > >> > it more clear when they haven't been initialized? >> > > > That was a confusing sentence. Change "when they haven't been >> > initialized" > >> to "when getSerializedSize() hasn't been called". >> > > > > >> > On Tue, Nov 24, 2009 at 7:04 PM, <mailto:jas...@google.com> wrote: >> > >> >> Reviewers: kenton, >> >> >> >> Description: >> >> Fix Issue 136: the memoized serialized size for packed fields may >> > not > >> >> be properly set. writeTo() may be invoked without a call to >> >> getSerializedSize(), so the generated serialization methods would >> >> write a length of 0 for non-empty packed fields. Since the object >> >> is immutable, we know that the memoized size is 0 or set to the >> >> correct size. In the generated code, check to see if the memoized >> >> size is 0, and if so, call getSerializedSize() before actually >> >> emitting the field. >> >> >> >> Tested: new unittest case in WireFormatTest.java now passes >> >> >> >> >> >> >> >> Please review this at http://codereview.appspot.com/157169 >> >> >> >> Affected files: >> >> M java/src/test/java/com/google/protobuf/WireFormatTest.java >> >> M src/google/protobuf/compiler/java/java_primitive_field.cc >> >> >> >> >> >> Index: java/src/test/java/com/google/protobuf/WireFormatTest.java >> >> =================================================================== >> >> --- java/src/test/java/com/google/protobuf/WireFormatTest.java >> > (revision > >> >> 246) >> >> +++ java/src/test/java/com/google/protobuf/WireFormatTest.java >> > (working > >> >> copy) >> >> @@ -102,6 +102,28 @@ >> >> assertEquals(rawBytes, rawBytes2); >> >> } >> >> >> >> + public void testSerializationPackedWithoutGetSerializedSize() >> >> + throws Exception { >> >> + // Write directly to an OutputStream, without invoking >> >> getSerializedSize() >> >> + // This used to be a bug where the size of a packed field was >> >> incorrect, >> >> + // since getSerializedSize() was never invoked. >> >> + TestPackedTypes message = TestUtil.getPackedSet(); >> >> + >> >> + // Directly construct a CodedOutputStream around the actual >> >> OutputStream, >> >> + // because writeTo() now invokes getSerializedSize(); >> >> + ByteArrayOutputStream outputStream = new >> > ByteArrayOutputStream(); > >> >> + CodedOutputStream codedOutput = >> >> CodedOutputStream.newInstance(outputStream); >> >> + >> >> + message.writeTo(codedOutput); >> >> + >> >> + codedOutput.flush(); >> >> + >> >> + TestPackedTypes message2 = TestPackedTypes.parseFrom( >> >> + outputStream.toByteArray()); >> >> + >> >> + TestUtil.assertPackedFieldsSet(message2); >> >> + } >> >> + >> >> public void testSerializeExtensionsLite() throws Exception { >> >> // TestAllTypes and TestAllExtensions should have compatible >> > wire > >> >> formats, >> >> // so if we serialize a TestAllExtensions then parse it as >> >> TestAllTypes >> >> Index: src/google/protobuf/compiler/java/java_primitive_field.cc >> >> =================================================================== >> >> --- src/google/protobuf/compiler/java/java_primitive_field.cc >> > (revision > >> >> 246) >> >> +++ src/google/protobuf/compiler/java/java_primitive_field.cc >> > (working > >> >> copy) >> >> @@ -384,8 +384,17 @@ >> >> void RepeatedPrimitiveFieldGenerator:: >> >> GenerateSerializationCode(io::Printer* printer) const { >> >> if (descriptor_->options().packed()) { >> >> + // writeTo() may be called without getSerializedSize() ever >> > having > >> >> been >> >> + // called, so we may need to compute the length of the packed >> > data. > >> >> Since >> >> + // the object is immutable, we know that the memoized size is >> > either > >> >> set to >> >> + // 0 (via object initialization) or else it has the correct >> > size from > >> >> a >> >> + // previous getSerializedSize() call. If the field is not >> > empty and > >> >> the size >> >> + // has not yet been computed, just call getSerializedSize() >> >> printer->Print(variables_, >> >> "if (get$capitalized_name$List().size() > 0) {\n" >> >> + " if ($name$MemoizedSerializedSize == 0) {\n" >> >> + " getSerializedSize();\n" >> >> + " }\n" >> >> " output.writeRawVarint32($tag$);\n" >> >> " output.writeRawVarint32($name$MemoizedSerializedSize);\n" >> >> "}\n" >> >> >> >> >> >> >> > >> > > > > > http://codereview.appspot.com/157169 > -- You received this message because you are subscribed to the Google Groups "Protocol Buffers" group. To post to this group, send email to proto...@googlegroups.com. To unsubscribe from this group, send email to protobuf+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.