mapbox / pbf

A low-level, lightweight protocol buffers implementation in JavaScript.
BSD 3-Clause "New" or "Revised" License
801 stars 107 forks source link

Possible incorrect oneof serealization #102

Closed farwayer closed 4 months ago

farwayer commented 5 years ago

Library should serialize default values of oneof field in any case to be possible to understand which one was set. Decoding fix for oneof was done in #51 for #54. But encoding is still incorrect. Comparison with other libraries:

message Id {
  oneof type {
    uint64 numId = 1;
    double doubleId = 2;
    string strId = 3;
  }
}
const protobufjs = require('protobufjs');
const google_pb = require('../gen/rpc_pb');
const Pbf = require('pbf');
const {Id} = require('./rpc');

const Data = {numId: 0};

function testGoogle() {
  const id = new google_pb.Id();
  id.setNumid(Data.numId);
  const s = id.serializeBinary();

  const d = google_pb.Id.deserializeBinary(s);

  console.log(
    'google-protobuf',
    Buffer.from(s),
    d.getTypeCase() === google_pb.Id.TypeCase.NUMID,
  );
}

async function testProtobufjs() {
  const root = await protobufjs.load('./src/rpc.proto');
  const Id = root.lookupType('Id');
  const data = Id.create(Data);
  const s = Id.encode(data).finish();

  const d = Id.decode(s);

  console.log(
    'protobufjs',
    s,
    d.type === 'numId',
  );
}

function testPbf() {
  const pbf = new Pbf();
  Id.write(Data, pbf);
  const s = pbf.finish();

  const d = Id.read(new Pbf(s));

  console.log(
    'pbf',
    Buffer.from(s),
    d.type === 'numId',
  );
}

async function test() {
  testGoogle();
  await testProtobufjs();
  testPbf();
}

test();

Result:

google-protobuf <Buffer 08 00> true
protobufjs <Buffer 08 00> true
pbf <Buffer > false
mourner commented 4 months ago

Fixed in v4.0.