[
https://issues.apache.org/jira/browse/THRIFT-2933?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14277300#comment-14277300
]
Randy Abernethy commented on THRIFT-2933:
-----------------------------------------
Hey Tom,
Thanks for the comment. Perhaps we agree conceptually. Here's where I am going
with this:
I would like to see all node protocol code migrated into files something like
this:
- thrift/lib/nodejs/TBinaryProtocol.js
- thrift/lib/nodejs/TCompactProtocol.js
- thrift/lib/nodejs/TJSONProtocol.js
with protocol.js as a pass through requirer for compatibility.
and all nodejs transports in files something like this:
- thrift/lib/nodejs/TFramedTransport.js
- thrift/lib/nodejs/TBufferedTransport.js
same story with transport.js (we also need to allow transports to be stacked
like most other language implementations)
So at the end of the day TBinaryProtocol (the object inside protocol.js) and
binary.js (the entire file) will move into TBinaryProtocol.js. This will
provide an implementation pattern and file isolation for those wishing to add
new protocols and transports (TCipherTransport, TSnappyProtocol, etc.).
The code file location and file naming convention above is adhered to by almost
all of the Apache Thrift languages, making Node.js harder to navigate right now
for folks familiar with Thrift. It also artificially intertwines
protocols/transports that really have nothing to do with each other.
Interesting to note that the only call (coupling) TCompactProtocol has to
binary.js is writeDouble(), which is the exact cause of this bug ( ! ). Had I
not tried to reuse and instead focused more on encapsulation this bug would not
have ended up in the code.
Hopefully with this road map the request makes more sense.
-Randy
> v0.9.2: doubles encoded in node with compact protocol cannot be decoded by
> python
> ---------------------------------------------------------------------------------
>
> Key: THRIFT-2933
> URL: https://issues.apache.org/jira/browse/THRIFT-2933
> Project: Thrift
> Issue Type: Bug
> Components: Node.js - Library
> Affects Versions: 0.9.2
> Reporter: Dan Heller
> Attachments: double-endiannes-2.patch, little-endian.patch,
> thrift-double.tgz
>
>
> I've noticed that with Thrift v0.9.2, using the Compact protocol, I can't
> encode doubles in node and decode them in python. It looks like in python,
> we're decoding little-endian for compact and big-endian for binary, and in
> node, writing big-endian in all cases (therefore, Binary works fine). I've
> attached a test program to show this behavior. I have not found the thrift
> binary spec, so I'm not sure which side is wrong.
> {code}
> [~/thrift-double]$ thrift --version
> Thrift version 0.9.2
> [~/thrift-double]$ grep -i thrift package.json
> "thrift": "0.9.2"
> "compile": "thrift --gen js:node --gen py test.thrift"
> [~/thrift-double]$ pip show thrift
> ---
> Name: thrift
> Version: 0.9.2
> Location: /Library/Python/2.7/site-packages
> Requires:
> [~/thrift-double]$ npm run compile
> > [email protected] compile /Users/dh/thrift-double
> > thrift --gen js:node --gen py test.thrift
> [~/thrift-double]$ node test.js binary | python test.py binary
> Trying to send { intField: 100, doubleField: 99.88 }
> Reading with binary protocol.
> Got test object: TestType(intField=100, doubleField=99.88)
> [~/thrift-double]$ node test.js compact | python test.py compact
> Trying to send { intField: 100, doubleField: 99.88 }
> Reading with compact protocol.
> Got test object: TestType(intField=100, doubleField=-2.24248483894553e-38)
> [~/thrift-double]$
> {code}
> I notice the following snippets.
> * TBinaryProtocol.py: network format (big-endian)
> {code}
> def readDouble(self):
> buff = self.trans.readAll(8)
> val, = unpack('!d', buff)
> return val
> {code}
> * TCompactProtocol.py: little-endian
> {code}
> def readDouble(self):
> buff = self.trans.readAll(8)
> val, = unpack('<d', buff)
> return val
> {code}
> * binary.js: my best IEEE floating point days are behind me but this looks
> big-endian. In any case it's used for both compact and binary.
> {code}
> exports.writeDouble = function(buff, v) {
> var m, e, c;
> buff[0] = (v < 0 ? 0x80 : 0x00);
> v = Math.abs(v);
> if (v !== v) {
> // NaN, use QNaN IEEE format
> m = 2251799813685248;
> e = 2047;
> } else if (v === Infinity) {
> m = 0;
> e = 2047;
> } else {
> e = Math.floor(Math.log(v) / Math.LN2);
> c = Math.pow(2, -e);
> if (v * c < 1) {
> e--;
> c *= 2;
> }
> if (e + 1023 >= 2047)
> {
> // Overflow
> m = 0;
> e = 2047;
> }
> else if (e + 1023 >= 1)
> {
> // Normalized - term order matters, as Math.pow(2, 52-e) and
> v*Math.pow(2, 52) can overflow
> m = (v*c-1) * POW_52;
> e += 1023;
> }
> else
> {
> // Denormalized - also catches the '0' case, somewhat by chance
> m = (v * POW_1022) * POW_52;
> e = 0;
> }
> }
> buff[1] = (e << 4) & 0xf0;
> buff[0] |= (e >> 4) & 0x7f;
> buff[7] = m & 0xff;
> m = Math.floor(m / POW_8);
> buff[6] = m & 0xff;
> m = Math.floor(m / POW_8);
> buff[5] = m & 0xff;
> m = Math.floor(m / POW_8);
> buff[4] = m & 0xff;
> m >>= 8;
> buff[3] = m & 0xff;
> m >>= 8;
> buff[2] = m & 0xff;
> m >>= 8;
> buff[1] |= m & 0x0f;
> return buff;
> };
> {code}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)