node.jsprotocol-buffersprotobufjs

protobufjs : encoding/decoding a message that has an Any component


I am using protobufjs 6.6.3 (running on nodejs 6.9.1) On short, I am trying to encode/decode a message that has a component of type Any and I am wondering if I am doing it right...

syntax = "proto3";
import "google/protobuf/any.proto";

package myTest;

message TestMessage {
  string message = 1;
  google.protobuf.Any details = 2;
}

My initial question was : what is happening when I am decoding a message of type TestMessage : does it automatically decodes the Any part as well, or I need to do it 'manually'?
Briefly, this is what I did:

Code:

const protobuf = require('protobufjs');
const protoFile = __dirname + '/testAnyProto.proto';

function AnyMessageType(properties) {
    protobuf.Message.call(this, properties); // call the super constructor
}

var root = protobuf.loadSync(protoFile);
protobuf.Class.create(root.lookup('google.protobuf.Any'), AnyMessageType);

var sampleBuffer = new Buffer('ABCDEF', 'utf8');
var sampleAny = new AnyMessageType({
    type_url: "some.type",
    value: sampleBuffer
});

var sampleAnyEncodedBuffer = AnyMessageType.encode(sampleAny).finish();
var sampleAnyEncodedDecoded = AnyMessageType.decode(sampleAnyEncodedBuffer);
//just checking if I am getting back 'ABCDEF' and... I am
console.log(sampleAnyEncodedDecoded.value.toString('utf8'));

var TestMessageType = root.lookup('myTest.TestMessage');
// Create a new message
var testMessage = TestMessageType.create({
    message: 'Some message',
    details: sampleAny //??? when I decode a testMessage, it creates an AnyMessageType, so I assume I am right
});

var encodedTestMessage = TestMessageType.encode(testMessage).finish();
var decodedEncodedTestMessage = TestMessageType.decode(encodedTestMessage);
console.log(decodedEncodedTestMessage.details.value.toString('utf8'));

OK... so, the questions:

  1. When I am building a TestMessage, details is expected (as per proto) to be filled with an AnyMessage message, not with an encoded AnyMessage message, correct?
  2. The decoding of an encoded TestMessage message, does not automatically decode the AnyMessage component (details), correct? At least, this is how it looks to me...
  3. What puzzles me the most, and therefore I need the above confirmations ... where am I supposed to use the AnyMessage encoding/decoding (I mean sampleAnyEncodedBuffer = AnyMessageType.encode(sampleAny).finish() call and the decode one)? Just for encoding/decoding simple AnyMessage (by simple I mean not part of a 'parent' message)?
    Let me put it like this : I am trying to match the existing Java pack/unpack functions.In my example, I am now 'associating' these with the buffer<->string conversion (see my last console.log line) and I don't see the need of calling AnyMessageType.decode... am I wrong?

Solution

  • Java pack-unpack is used when Any transports another protobuf message encoded in it. When your Any transports just a string, then you obviously don't need to call any decode. Your decode/unpack is value.toString('utf-8'). You are accessing directly Any's members type_url and value, which is what Java's pack-unpack is abstracting you from.

    When you would want to transport a protobuf ThatMessageType in details instead of simple string, then you would need ThatMessageType.encode() instead of just creating a Buffer, and ThatMessageType.decode() instead of calling toString.