More tricky. Given a stream and an instance, I'm trying to get the
Descriptor by calling Message#getDescriptorForType() on the instance
and passing the return value, along with an input stream, to
DynamicMessage#parseFrom(Descriptor,input). I then cast the
DynamicMessage that is returned by parseFrom to the same type of the
instance that is given to me.
The problem that I'm encountering is during deserialization. I'm
getting an InvalidProtocolBufferException. Here's the trace:
...
What's curious about this is that my .proto files each only have one
field in each Message, and each of those fields has a tag of 1. None
of my tags are 0.
That won't work. DynamicMessage is a different class; it does not know how to instantiate the protocol-compiler-generated version of the class. Instead, you should do:Message result =messageInstance.newBuilderForType().mergeFrom(input).build();Actually, you should check isInitialized() before calling build(), or use buildPartial() instead, but that's a separate issue.
The protocol compiler would not allow you to use tag zero anyway. It looks like your input data is not identical to the data written by the sender.
On Tue, Sep 9, 2008 at 1:16 AM, Kenton Varda <ken...@google.com> wrote:That won't work. DynamicMessage is a different class; it does not know how to instantiate the protocol-compiler-generated version of the class. Instead, you should do:Message result =messageInstance.newBuilderForType().mergeFrom(input).build();Actually, you should check isInitialized() before calling build(), or use buildPartial() instead, but that's a separate issue.
I changed my deserializing code to use the above, but I'm getting the same exception. I also tried to call isInitialized() on the instance given to me, and the instance is not initialized.
The protocol compiler would not allow you to use tag zero anyway. It looks like your input data is not identical to the data written by the sender.
I'm confident that the sender data is the same data that is created when I serialize.
Perhaps I'm serializing incorrectly? I'm creating a CodedOutputStream given an OutputStream and passing that to writeTo.
However, I'm not using a CodedInputStream to deserialize. Should I be using Coded or non-Coded streams?
On Mon, Sep 8, 2008 at 6:18 PM, Alex Loddengaard <alexlod...@gmail.com> wrote:
On Tue, Sep 9, 2008 at 1:16 AM, Kenton Varda <ken...@google.com> wrote:That won't work. DynamicMessage is a different class; it does not know how to instantiate the protocol-compiler-generated version of the class. Instead, you should do:Message result =messageInstance.newBuilderForType().mergeFrom(input).build();Actually, you should check isInitialized() before calling build(), or use buildPartial() instead, but that's a separate issue.
I changed my deserializing code to use the above, but I'm getting the same exception. I also tried to call isInitialized() on the instance given to me, and the instance is not initialized.That message instance is probably a default instance. isInitialized() will always be false on those, unless it has no required fields at all.
To clarify: In my original message I was saying that you should call isInitialized() on the builder returned by mergeFrom(), to make sure the parsed message is complete, before you call build().
I have a follow-up question:
Will using messageInstance.newBuilderForType().mergeFrom(input).build(); work for a stream that contains trailing binary information?
I should revise my problem slightly. I had said that I am given an instance of a Message class when deserializing. This is true, though sometimes that instance is null. In the cases when it's null, I'm not able to call newBuilderForType() on it. I'm not able to call getDefaultInstance(), either. This is now problematic, though there may be a work around. Also given to me is a Class instance of the Message. I'm using Reflection to instantiate a new Message instance, then getDefaultInstance() to get the default instance, and then I'm calling newBuilderForType(). Is this problematic?
Kenton Varda wrote:
> On Mon, Sep 8, 2008 at 9:11 PM, Alex Loddengaard
> <alexlod...@gmail.com <mailto:alexlod...@gmail.com>> wrote:
>
> I have a follow-up question:
>
> Will using
> /messageInstance.newBuilderForType().mergeFrom(input).build();/
> work for a stream that contains trailing binary information?
>
>
> No, it won't work. Protocol buffers are not self-delimiting. They
> assume that the input you provide is supposed to be one complete
> message, not a message possibly followed by other stuff.
>
> You will need to somehow communicate the size of the message and make
> sure to limit the input to that size.
Aha. This <binary>message<binary> case is one of the heretofore
hypothetical use cases I am discussing in the adjacent thread on this
mailing list / group. The thread is online at
http://groups.google.com/group/protobuf/browse_thread/thread/b0ce2c7d8b05896e?hl=en
and was spawned from
http://groups.google.com/group/protobuf/browse_thread/thread/b0ce2c7d8b05896e?hl=en#
This is mainly myself, Jon, and Kenton slowly forming a consensus on the
right API for delimited messages. I had proposed simply adding the
length (varint) before the message, and Kenton demonstrated c++ code for
this. Jon proposed adding a field number / wiretype tag before the
length and message, which makes it look much more like a protocol-buffer
field on the wire.
What do you need Alex?
--
Chris