[ https://issues.apache.org/jira/browse/THRIFT-2933?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14275615#comment-14275615 ]
Dan Heller commented on THRIFT-2933: ------------------------------------ [~codesf] thanks for explaining. Sure, I can do it that way. I'll take a crack at it now. > 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: 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 > > double-decode-bug@0.0.1 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)