RespEncoder.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.RespEncoder = void 0;
  4. const Writer_1 = require("@jsonjoy.com/util/lib/buffers/Writer");
  5. const utf8_1 = require("@jsonjoy.com/util/lib/strings/utf8");
  6. const extensions_1 = require("./extensions");
  7. const JsonPackExtension_1 = require("../JsonPackExtension");
  8. const REG_RN = /[\r\n]/;
  9. const isSafeInteger = Number.isSafeInteger;
  10. class RespEncoder {
  11. constructor(writer = new Writer_1.Writer()) {
  12. this.writer = writer;
  13. }
  14. encode(value) {
  15. this.writeAny(value);
  16. return this.writer.flush();
  17. }
  18. encodeToSlice(value) {
  19. this.writeAny(value);
  20. return this.writer.flushSlice();
  21. }
  22. writeAny(value) {
  23. switch (typeof value) {
  24. case 'number':
  25. return this.writeNumber(value);
  26. case 'string':
  27. return this.writeStr(value);
  28. case 'boolean':
  29. return this.writeBoolean(value);
  30. case 'object': {
  31. if (!value)
  32. return this.writeNull();
  33. if (value instanceof Array)
  34. return this.writeArr(value);
  35. if (value instanceof Uint8Array)
  36. return this.writeBin(value);
  37. if (value instanceof Error)
  38. return this.writeErr(value.message);
  39. if (value instanceof Set)
  40. return this.writeSet(value);
  41. if (value instanceof JsonPackExtension_1.JsonPackExtension) {
  42. if (value instanceof extensions_1.RespPush)
  43. return this.writePush(value.val);
  44. if (value instanceof extensions_1.RespVerbatimString)
  45. return this.writeVerbatimStr('txt', value.val);
  46. if (value instanceof extensions_1.RespAttributes)
  47. return this.writeAttr(value.val);
  48. }
  49. return this.writeObj(value);
  50. }
  51. case 'undefined':
  52. return this.writeUndef();
  53. case 'bigint':
  54. return this.writeBigInt(value);
  55. default:
  56. return this.writeUnknown(value);
  57. }
  58. }
  59. writeLength(length) {
  60. const writer = this.writer;
  61. if (length < 100) {
  62. if (length < 10) {
  63. writer.u8(length + 48);
  64. return;
  65. }
  66. const octet1 = length % 10;
  67. const octet2 = (length - octet1) / 10;
  68. writer.u16(((octet2 + 48) << 8) + octet1 + 48);
  69. return;
  70. }
  71. let digits = 1;
  72. let pow = 10;
  73. while (length >= pow) {
  74. digits++;
  75. pow *= 10;
  76. }
  77. writer.ensureCapacity(digits);
  78. const uint8 = writer.uint8;
  79. const x = writer.x;
  80. const newX = x + digits;
  81. let i = newX - 1;
  82. while (i >= x) {
  83. const remainder = length % 10;
  84. uint8[i--] = remainder + 48;
  85. length = (length - remainder) / 10;
  86. }
  87. writer.x = newX;
  88. }
  89. encodeCmd(args) {
  90. this.writeCmd(args);
  91. return this.writer.flush();
  92. }
  93. writeCmd(args) {
  94. const length = args.length;
  95. this.writeArrHdr(length);
  96. for (let i = 0; i < length; i++) {
  97. const arg = args[i];
  98. if (arg instanceof Uint8Array)
  99. this.writeBin(arg);
  100. else
  101. this.writeBulkStrAscii(arg + '');
  102. }
  103. }
  104. encodeCmdUtf8(args) {
  105. this.writeCmdUtf8(args);
  106. return this.writer.flush();
  107. }
  108. writeCmdUtf8(args) {
  109. const length = args.length;
  110. this.writeArrHdr(length);
  111. for (let i = 0; i < length; i++)
  112. this.writeArgUtf8(args[i]);
  113. }
  114. writeArgUtf8(arg) {
  115. if (arg instanceof Uint8Array)
  116. return this.writeBin(arg);
  117. else
  118. this.writeBulkStr(arg + '');
  119. }
  120. writeNull() {
  121. this.writer.u8u16(95, 3338);
  122. }
  123. writeNullStr() {
  124. this.writer.u8u32(36, 45 * 0x1000000 +
  125. 49 * 0x10000 +
  126. 3338);
  127. }
  128. writeNullArr() {
  129. this.writer.u8u32(42, 45 * 0x1000000 +
  130. 49 * 0x10000 +
  131. 3338);
  132. }
  133. writeBoolean(bool) {
  134. this.writer.u32(bool
  135. ? 35 * 0x1000000 +
  136. 116 * 0x10000 +
  137. 3338
  138. : 35 * 0x1000000 +
  139. 102 * 0x10000 +
  140. 3338);
  141. }
  142. writeNumber(num) {
  143. if (isSafeInteger(num))
  144. this.writeInteger(num);
  145. else if (typeof num === 'bigint')
  146. this.writeBigInt(num);
  147. else
  148. this.writeFloat(num);
  149. }
  150. writeBigInt(int) {
  151. const writer = this.writer;
  152. writer.u8(40);
  153. writer.ascii(int + '');
  154. writer.u16(3338);
  155. }
  156. writeInteger(int) {
  157. const writer = this.writer;
  158. writer.u8(58);
  159. writer.ascii(int + '');
  160. writer.u16(3338);
  161. }
  162. writeUInteger(uint) {
  163. this.writeInteger(uint);
  164. }
  165. writeFloat(float) {
  166. const writer = this.writer;
  167. writer.u8(44);
  168. switch (float) {
  169. case Infinity:
  170. writer.u8u16(105, (110 << 8) |
  171. 102);
  172. break;
  173. case -Infinity:
  174. writer.u32((45 * 0x1000000 +
  175. 105 * 0x10000 +
  176. (110 << 8)) |
  177. 102);
  178. break;
  179. default:
  180. if (float !== float)
  181. writer.u8u16(110, (97 << 8) |
  182. 110);
  183. else
  184. writer.ascii(float + '');
  185. break;
  186. }
  187. writer.u16(3338);
  188. }
  189. writeBin(buf) {
  190. const writer = this.writer;
  191. const length = buf.length;
  192. writer.u8(36);
  193. this.writeLength(length);
  194. writer.u16(3338);
  195. writer.buf(buf, length);
  196. writer.u16(3338);
  197. }
  198. writeBinHdr(length) {
  199. throw new Error('Not implemented');
  200. }
  201. writeStr(str) {
  202. const length = str.length;
  203. if (length < 64 && !REG_RN.test(str))
  204. this.writeSimpleStr(str);
  205. else
  206. this.writeVerbatimStr('txt', str);
  207. }
  208. writeStrHdr(length) {
  209. throw new Error('Not implemented');
  210. }
  211. writeSimpleStr(str) {
  212. const writer = this.writer;
  213. writer.u8(43);
  214. writer.ensureCapacity(str.length << 2);
  215. writer.utf8(str);
  216. writer.u16(3338);
  217. }
  218. writeSimpleStrAscii(str) {
  219. const writer = this.writer;
  220. writer.u8(43);
  221. writer.ascii(str);
  222. writer.u16(3338);
  223. }
  224. writeBulkStr(str) {
  225. const writer = this.writer;
  226. const size = (0, utf8_1.utf8Size)(str);
  227. writer.u8(36);
  228. this.writeLength(size);
  229. writer.u16(3338);
  230. writer.ensureCapacity(size);
  231. writer.utf8(str);
  232. writer.u16(3338);
  233. }
  234. writeBulkStrAscii(str) {
  235. const writer = this.writer;
  236. writer.u8(36);
  237. this.writeLength(str.length);
  238. writer.u16(3338);
  239. writer.ascii(str);
  240. writer.u16(3338);
  241. }
  242. writeAsciiStr(str) {
  243. const isSimple = !REG_RN.test(str);
  244. if (isSimple)
  245. this.writeSimpleStr(str);
  246. else
  247. this.writeBulkStrAscii(str);
  248. }
  249. writeVerbatimStr(encoding, str) {
  250. const writer = this.writer;
  251. const size = (0, utf8_1.utf8Size)(str);
  252. writer.u8(61);
  253. this.writeLength(size + 4);
  254. writer.u16(3338);
  255. writer.u32(encoding.charCodeAt(0) * 0x1000000 +
  256. (encoding.charCodeAt(1) << 16) +
  257. (encoding.charCodeAt(2) << 8) +
  258. 58);
  259. writer.ensureCapacity(size);
  260. writer.utf8(str);
  261. writer.u16(3338);
  262. }
  263. writeErr(str) {
  264. if (str.length < 64 && !REG_RN.test(str))
  265. this.writeSimpleErr(str);
  266. else
  267. this.writeBulkErr(str);
  268. }
  269. writeSimpleErr(str) {
  270. const writer = this.writer;
  271. writer.u8(45);
  272. writer.ensureCapacity(str.length << 2);
  273. writer.utf8(str);
  274. writer.u16(3338);
  275. }
  276. writeBulkErr(str) {
  277. const writer = this.writer;
  278. const size = (0, utf8_1.utf8Size)(str);
  279. writer.u8(33);
  280. this.writeLength(size);
  281. writer.u16(3338);
  282. writer.ensureCapacity(size);
  283. writer.utf8(str);
  284. writer.u16(3338);
  285. }
  286. writeArr(arr) {
  287. const writer = this.writer;
  288. const length = arr.length;
  289. writer.u8(42);
  290. this.writeLength(length);
  291. writer.u16(3338);
  292. for (let i = 0; i < length; i++)
  293. this.writeAny(arr[i]);
  294. }
  295. writeArrHdr(length) {
  296. const writer = this.writer;
  297. writer.u8(42);
  298. this.writeLength(length);
  299. writer.u16(3338);
  300. }
  301. writeObj(obj) {
  302. const writer = this.writer;
  303. const keys = Object.keys(obj);
  304. const length = keys.length;
  305. writer.u8(37);
  306. this.writeLength(length);
  307. writer.u16(3338);
  308. for (let i = 0; i < length; i++) {
  309. const key = keys[i];
  310. this.writeStr(key);
  311. this.writeAny(obj[key]);
  312. }
  313. }
  314. writeObjHdr(length) {
  315. const writer = this.writer;
  316. writer.u8(37);
  317. this.writeLength(length);
  318. writer.u16(3338);
  319. }
  320. writeAttr(obj) {
  321. const writer = this.writer;
  322. const keys = Object.keys(obj);
  323. const length = keys.length;
  324. writer.u8(124);
  325. this.writeLength(length);
  326. writer.u16(3338);
  327. for (let i = 0; i < length; i++) {
  328. const key = keys[i];
  329. this.writeStr(key);
  330. this.writeAny(obj[key]);
  331. }
  332. }
  333. writeSet(set) {
  334. const writer = this.writer;
  335. const length = set.size;
  336. writer.u8(126);
  337. this.writeLength(length);
  338. writer.u16(3338);
  339. for (let i = 0; i < length; i++)
  340. set.forEach((value) => this.writeAny(value));
  341. }
  342. writePush(elements) {
  343. const writer = this.writer;
  344. const length = elements.length;
  345. writer.u8(62);
  346. this.writeLength(length);
  347. writer.u16(3338);
  348. for (let i = 0; i < length; i++)
  349. this.writeAny(elements[i]);
  350. }
  351. writeUnknown(value) {
  352. this.writeNull();
  353. }
  354. writeUndef() {
  355. this.writeNull();
  356. }
  357. writeRn() {
  358. this.writer.u16(3338);
  359. }
  360. writeStartStr() {
  361. this.writer.u32(36 * 0x1000000 +
  362. (63 << 16) +
  363. 3338);
  364. }
  365. writeStrChunk(str) {
  366. const writer = this.writer;
  367. writer.u8(59);
  368. const size = (0, utf8_1.utf8Size)(str);
  369. this.writeLength(size);
  370. writer.u16(3338);
  371. writer.ensureCapacity(size);
  372. writer.utf8(str);
  373. writer.u16(3338);
  374. }
  375. writeEndStr() {
  376. this.writer.u32(59 * 0x1000000 +
  377. (48 << 16) +
  378. 3338);
  379. }
  380. writeStartBin() {
  381. this.writer.u32(36 * 0x1000000 +
  382. (63 << 16) +
  383. 3338);
  384. }
  385. writeBinChunk(buf) {
  386. const writer = this.writer;
  387. const length = buf.length;
  388. writer.u8(59);
  389. this.writeLength(length);
  390. writer.u16(3338);
  391. writer.buf(buf, length);
  392. writer.u16(3338);
  393. }
  394. writeEndBin() {
  395. this.writer.u32(59 * 0x1000000 +
  396. (48 << 16) +
  397. 3338);
  398. }
  399. writeStartArr() {
  400. this.writer.u32(42 * 0x1000000 +
  401. (63 << 16) +
  402. 3338);
  403. }
  404. writeArrChunk(item) {
  405. this.writeAny(item);
  406. }
  407. writeEndArr() {
  408. this.writer.u8u16(46, 3338);
  409. }
  410. writeStartObj() {
  411. this.writer.u32(37 * 0x1000000 +
  412. (63 << 16) +
  413. 3338);
  414. }
  415. writeObjChunk(key, value) {
  416. this.writeStr(key);
  417. this.writeAny(value);
  418. }
  419. writeEndObj() {
  420. this.writer.u8u16(46, 3338);
  421. }
  422. }
  423. exports.RespEncoder = RespEncoder;
  424. //# sourceMappingURL=RespEncoder.js.map