capnproto/node-capnp

Preserve Types

sachnk opened this issue · 3 comments

Hi,

It seems like when parsing capnp messages, it loses type information. For example, if I serialize the following node.js object:

{
  a: 10,
  b: 0,
  c: "string"
}

And then parse the same serialized object back with capnp.parse(), my integers become strings:

{
  a: "10",
  b: "0",
  c: "string"
}

Can this be avoided?

Hi @sachnk,

This happens if a and b are declared as 64-bit integers. JavaScript cannot precisely represent 64-bit integers, since it represents all numbers as double-width floating points, which can only represent up to 52 bits before it loses precision. Because of this, it is common practice to represent 64-bit integers as strings, so that they don't lose information and you can pass them to e.g. a BigInt library.

Here are your options:

  • If you don't need 64 bits, you can change the type definitions to Int32/UInt32 instead. (Or Float64, to exactly match what JavaScript supports.)
  • If you are OK with losing precision, you can add a + prefix when accessing the field to make JavaScript coerce it to a number. E.g.: +myStruct.a
  • You can use the big-integer npm library to parse the number and use it without losing precision.

Ah, I see. Thanks for clarifying. Is there a way to instruct capnp.parse() to parse Int64 as big-integer instead of string so I can avoid having a transformation layer?

Sorry, there isn't. Since the translation happens in C++ extension code it would be pretty invasive to string in an external library there, but I'd accept a PR if someone really wants to do the work.