decoder.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. #pragma once
  2. #if !defined(__STDC_FORMAT_MACROS)
  3. #define __STDC_FORMAT_MACROS
  4. #endif
  5. #include <nan.h>
  6. #include <zlib.h>
  7. #include <cinttypes>
  8. #include <cstdio>
  9. #include "../cpp/sysdep.h"
  10. using namespace v8;
  11. #define THROW(msg) Nan::ThrowError(msg); isInvalid = true; printf("[Error %s:%d] %s\n", __FILE__, __LINE__, msg)
  12. class Decoder {
  13. public:
  14. Decoder(const Nan::TypedArrayContents<uint8_t>& array)
  15. : data(*array)
  16. , size(array.length())
  17. , isInvalid(false)
  18. , offset(0)
  19. {
  20. const auto version = read8();
  21. if (version != FORMAT_VERSION) {
  22. THROW("Bad version number.");
  23. isInvalid = true;
  24. }
  25. }
  26. Decoder(const uint8_t* data_, size_t length_, bool skipVersion = false)
  27. : data(data_)
  28. , size(length_)
  29. , isInvalid(false)
  30. , offset(0)
  31. {
  32. if (!skipVersion) {
  33. const auto version = read8();
  34. if (version != FORMAT_VERSION) {
  35. THROW("Bad version number.");
  36. isInvalid = true;
  37. }
  38. }
  39. }
  40. uint8_t read8() {
  41. if (offset + sizeof(uint8_t) > size) {
  42. THROW("Reading a byte passes the end of the buffer.");
  43. return 0;
  44. }
  45. auto val = *reinterpret_cast<const uint8_t*>(data + offset);
  46. offset += sizeof(uint8_t);
  47. return val;
  48. }
  49. uint16_t read16() {
  50. if (offset + sizeof(uint16_t) > size) {
  51. THROW("Reading two bytes passes the end of the buffer.");
  52. return 0;
  53. }
  54. uint16_t val = _erlpack_be16(*reinterpret_cast<const uint16_t*>(data + offset));
  55. offset += sizeof(uint16_t);
  56. return val;
  57. }
  58. uint32_t read32() {
  59. if (offset + sizeof(uint32_t) > size) {
  60. THROW("Reading three bytes passes the end of the buffer.");
  61. return 0;
  62. }
  63. uint32_t val = _erlpack_be32(*reinterpret_cast<const uint32_t*>(data + offset));
  64. offset += sizeof(uint32_t);
  65. return val;
  66. }
  67. uint64_t read64() {
  68. if (offset + sizeof(uint64_t) > size) {
  69. THROW("Reading four bytes passes the end of the buffer.");
  70. return 0;
  71. }
  72. uint64_t val = _erlpack_be64(*reinterpret_cast<const uint64_t*>(data + offset));
  73. offset += sizeof(val);
  74. return val;
  75. }
  76. Local<Value> decodeSmallInteger() {
  77. return Nan::New<Integer>(read8());
  78. }
  79. Local<Value> decodeInteger() {
  80. return Nan::New<Integer>((int32_t)read32());
  81. }
  82. Local<Value> decodeArray(uint32_t length) {
  83. Local<Object> array = Nan::New<Array>(length);
  84. for(uint32_t i = 0; i < length; ++i) {
  85. auto value = unpack();
  86. if (isInvalid) {
  87. return Nan::Undefined();
  88. }
  89. array->Set(i, value);
  90. }
  91. return array;
  92. }
  93. Local<Value> decodeList() {
  94. const uint32_t length = read32();
  95. auto array = decodeArray(length);
  96. const auto tailMarker = read8();
  97. if (tailMarker != NIL_EXT) {
  98. THROW("List doesn't end with a tail marker, but it must!");
  99. return Nan::Null();
  100. }
  101. return array;
  102. }
  103. Local<Value> decodeTuple(uint32_t length) {
  104. return decodeArray(length);
  105. }
  106. Local<Value> decodeNil() {
  107. Local<Object> array = Nan::New<Array>(0);
  108. return array;
  109. }
  110. Local<Value> decodeMap() {
  111. const uint32_t length = read32();
  112. auto map = Nan::New<Object>();
  113. for(uint32_t i = 0; i < length; ++i) {
  114. const auto key = unpack();
  115. const auto value = unpack();
  116. if (isInvalid) {
  117. return Nan::Undefined();
  118. }
  119. map->Set(key, value);
  120. }
  121. return map;
  122. }
  123. const char* readString(uint32_t length) {
  124. if (offset + length > size) {
  125. THROW("Reading sequence past the end of the buffer.");
  126. return NULL;
  127. }
  128. const uint8_t* str = data + offset;
  129. offset += length;
  130. return (const char*)str;
  131. }
  132. Local<Value> processAtom(const char* atom, uint16_t length) {
  133. if (atom == NULL) {
  134. return Nan::Undefined();
  135. }
  136. if (length >= 3 && length <= 5) {
  137. if (length == 3 && strncmp(atom, "nil", 3) == 0) {
  138. return Nan::Null();
  139. }
  140. else if (length == 4 && strncmp(atom, "null", 4) == 0) {
  141. return Nan::Null();
  142. }
  143. else if(length == 4 && strncmp(atom, "true", 4) == 0) {
  144. return Nan::True();
  145. }
  146. else if (length == 5 && strncmp(atom, "false", 5) == 0) {
  147. return Nan::False();
  148. }
  149. }
  150. return Nan::New(atom, length).ToLocalChecked();
  151. }
  152. Local<Value> decodeAtom() {
  153. auto length = read16();
  154. const char* atom = readString(length);
  155. return processAtom(atom, length);
  156. }
  157. Local<Value> decodeSmallAtom() {
  158. auto length = read8();
  159. const char* atom = readString(length);
  160. return processAtom(atom, length);
  161. }
  162. Local<Value> decodeFloat() {
  163. const uint8_t FLOAT_LENGTH = 31;
  164. const char* floatStr = readString(FLOAT_LENGTH);
  165. if (floatStr == NULL) {
  166. return Nan::Undefined();
  167. }
  168. double number;
  169. char nullTerimated[FLOAT_LENGTH + 1] = {0};
  170. memcpy(nullTerimated, floatStr, FLOAT_LENGTH);
  171. auto count = sscanf(nullTerimated, "%lf", &number);
  172. if (count != 1) {
  173. THROW("Invalid float encoded.");
  174. return Nan::Null();
  175. }
  176. return Nan::New<Number>(number);
  177. }
  178. Local<Value> decodeNewFloat() {
  179. union {
  180. uint64_t ui64;
  181. double df;
  182. } val;
  183. val.ui64 = read64();
  184. return Nan::New<Number>(val.df);
  185. }
  186. Local<Value> decodeBig(uint32_t digits) {
  187. const uint8_t sign = read8();
  188. if (digits > 8) {
  189. THROW("Unable to decode big ints larger than 8 bytes");
  190. return Nan::Null();
  191. }
  192. uint64_t value = 0;
  193. uint64_t b = 1;
  194. for(uint32_t i = 0; i < digits; ++i) {
  195. uint64_t digit = read8();
  196. value += digit * b;
  197. b <<= 8;
  198. }
  199. if (digits <= 4) {
  200. if (sign == 0) {
  201. return Nan::New<Integer>(static_cast<uint32_t>(value));
  202. }
  203. const bool isSignBitAvailable = (value & (1 << 31)) == 0;
  204. if (isSignBitAvailable) {
  205. int32_t negativeValue = -static_cast<int32_t>(value);
  206. return Nan::New<Integer>(negativeValue);
  207. }
  208. }
  209. char outBuffer[32] = {0}; // 9223372036854775807
  210. const char* const formatString = sign == 0 ? "%" PRIu64 : "-%" PRIu64;
  211. const int res = sprintf(outBuffer, formatString, value);
  212. if (res < 0) {
  213. THROW("Unable to convert big int to string");
  214. return Nan::Null();
  215. }
  216. const uint8_t length = static_cast<const uint8_t>(res);
  217. return Nan::New(outBuffer, length).ToLocalChecked();
  218. }
  219. Local<Value> decodeSmallBig() {
  220. const auto bytes = read8();
  221. return decodeBig(bytes);
  222. }
  223. Local<Value> decodeLargeBig() {
  224. const auto bytes = read32();
  225. return decodeBig(bytes);
  226. }
  227. Local<Value> decodeBinaryAsString() {
  228. const auto length = read32();
  229. const char* str = readString(length);
  230. if (str == NULL) {
  231. return Nan::Undefined();
  232. }
  233. auto binaryString = Nan::New(str, length);
  234. return binaryString.ToLocalChecked();
  235. }
  236. Local<Value> decodeString() {
  237. const auto length = read16();
  238. const char* str = readString(length);
  239. if (str == NULL) {
  240. return Nan::Undefined();
  241. }
  242. auto binaryString = Nan::New(str, length);
  243. return binaryString.ToLocalChecked();
  244. }
  245. Local<Value> decodeStringAsList() {
  246. const auto length = read16();
  247. if (offset + length > size) {
  248. THROW("Reading sequence past the end of the buffer.");
  249. return Nan::Null();
  250. }
  251. Local<Object> array = Nan::New<Array>(length);
  252. for(uint16_t i = 0; i < length; ++i) {
  253. array->Set(i, decodeSmallInteger());
  254. }
  255. return array;
  256. }
  257. Local<Value> decodeSmallTuple() {
  258. return decodeTuple(read8());
  259. }
  260. Local<Value> decodeLargeTuple() {
  261. return decodeTuple(read32());
  262. }
  263. Local<Value> decodeCompressed() {
  264. const uint32_t uncompressedSize = read32();
  265. unsigned long sourceSize = uncompressedSize;
  266. uint8_t* outBuffer = (uint8_t*)malloc(uncompressedSize);
  267. const int ret = uncompress(outBuffer, &sourceSize, (const unsigned char*)(data + offset), (uLong)(size - offset));
  268. offset += sourceSize;
  269. if (ret != Z_OK) {
  270. free(outBuffer);
  271. THROW("Failed to uncompresss compressed item");
  272. return Nan::Null();
  273. }
  274. Decoder children(outBuffer, uncompressedSize, true);
  275. Nan::MaybeLocal<Value> value = children.unpack();
  276. free(outBuffer);
  277. return value.ToLocalChecked();
  278. }
  279. Local<Value> decodeReference() {
  280. auto reference = Nan::New<Object>();
  281. reference->Set(Nan::New("node").ToLocalChecked(), unpack());
  282. Local<Object> ids = Nan::New<Array>(1);
  283. ids->Set(0, Nan::New<Integer>(read32()));
  284. reference->Set(Nan::New("id").ToLocalChecked(), ids);
  285. reference->Set(Nan::New("creation").ToLocalChecked(), Nan::New<Integer>(read8()));
  286. return reference;
  287. }
  288. Local<Value> decodeNewReference() {
  289. auto reference = Nan::New<Object>();
  290. uint16_t len = read16();
  291. reference->Set(Nan::New("node").ToLocalChecked(), unpack());
  292. reference->Set(Nan::New("creation").ToLocalChecked(), Nan::New<Integer>(read8()));
  293. Local<Object> ids = Nan::New<Array>(len);
  294. for(uint16_t i = 0; i < len; ++i) {
  295. ids->Set(i, Nan::New<Integer>(read32()));
  296. }
  297. reference->Set(Nan::New("id").ToLocalChecked(), ids);
  298. return reference;
  299. }
  300. Local<Value> decodePort() {
  301. auto port = Nan::New<Object>();
  302. port->Set(Nan::New("node").ToLocalChecked(), unpack());
  303. port->Set(Nan::New("id").ToLocalChecked(), Nan::New<Integer>(read32()));
  304. port->Set(Nan::New("creation").ToLocalChecked(), Nan::New<Integer>(read8()));
  305. return port;
  306. }
  307. Local<Value> decodePID() {
  308. auto pid = Nan::New<Object>();
  309. pid->Set(Nan::New("node").ToLocalChecked(), unpack());
  310. pid->Set(Nan::New("id").ToLocalChecked(), Nan::New<Integer>(read32()));
  311. pid->Set(Nan::New("serial").ToLocalChecked(), Nan::New<Integer>(read32()));
  312. pid->Set(Nan::New("creation").ToLocalChecked(), Nan::New<Integer>(read8()));
  313. return pid;
  314. }
  315. Local<Value> decodeExport() {
  316. auto exp = Nan::New<Object>();
  317. exp->Set(Nan::New("mod").ToLocalChecked(), unpack());
  318. exp->Set(Nan::New("fun").ToLocalChecked(), unpack());
  319. exp->Set(Nan::New("arity").ToLocalChecked(), unpack());
  320. return exp;
  321. }
  322. Local<Value> unpack() {
  323. if (isInvalid) {
  324. return Nan::Undefined();
  325. }
  326. if(offset >= size) {
  327. THROW("Unpacking beyond the end of the buffer");
  328. return Nan::Undefined();
  329. }
  330. const auto type = read8();
  331. switch(type) {
  332. case SMALL_INTEGER_EXT:
  333. return decodeSmallInteger();
  334. case INTEGER_EXT:
  335. return decodeInteger();
  336. case FLOAT_EXT:
  337. return decodeFloat();
  338. case NEW_FLOAT_EXT:
  339. return decodeNewFloat();
  340. case ATOM_EXT:
  341. return decodeAtom();
  342. case SMALL_ATOM_EXT:
  343. return decodeSmallAtom();
  344. case SMALL_TUPLE_EXT:
  345. return decodeSmallTuple();
  346. case LARGE_TUPLE_EXT:
  347. return decodeLargeTuple();
  348. case NIL_EXT:
  349. return decodeNil();
  350. case STRING_EXT:
  351. return decodeStringAsList();
  352. case LIST_EXT:
  353. return decodeList();
  354. case MAP_EXT:
  355. return decodeMap();
  356. case BINARY_EXT:
  357. return decodeBinaryAsString();
  358. case SMALL_BIG_EXT:
  359. return decodeSmallBig();
  360. case LARGE_BIG_EXT:
  361. return decodeLargeBig();
  362. case REFERENCE_EXT:
  363. return decodeReference();
  364. case NEW_REFERENCE_EXT:
  365. return decodeNewReference();
  366. case PORT_EXT:
  367. return decodePort();
  368. case PID_EXT:
  369. return decodePID();
  370. case EXPORT_EXT:
  371. return decodeExport();
  372. case COMPRESSED:
  373. return decodeCompressed();
  374. default:
  375. THROW("Unsupported erlang term type identifier found");
  376. return Nan::Undefined();
  377. }
  378. return Nan::Undefined();
  379. }
  380. private:
  381. const uint8_t* const data;
  382. const size_t size;
  383. bool isInvalid;
  384. size_t offset;
  385. };