keys.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import { getAddress, orderedBinary } from './native.js';
  2. const REUSE_BUFFER_MODE = 512;
  3. const writeUint32Key = (key, target, start) => {
  4. (target.dataView || (target.dataView = new DataView(target.buffer, 0, target.length))).setUint32(start, key, true);
  5. return start + 4;
  6. };
  7. const readUint32Key = (target, start) => {
  8. return (target.dataView || (target.dataView = new DataView(target.buffer, 0, target.length))).getUint32(start, true);
  9. };
  10. const writeBufferKey = (key, target, start) => {
  11. target.set(key, start);
  12. return key.length + start;
  13. };
  14. const Uint8ArraySlice = Uint8Array.prototype.slice;
  15. const readBufferKey = (target, start, end) => {
  16. return Uint8ArraySlice.call(target, start, end);
  17. };
  18. let lastEncodedValue, bytes;
  19. export function applyKeyHandling(store) {
  20. if (store.encoding == 'ordered-binary') {
  21. store.encoder = store.decoder = {
  22. writeKey: orderedBinary.writeKey,
  23. readKey: orderedBinary.readKey,
  24. };
  25. }
  26. if (store.encoder && store.encoder.writeKey && !store.encoder.encode) {
  27. store.encoder.encode = function(value, mode) {
  28. if (typeof value !== 'object' && value && value === lastEncodedValue) {
  29. // reuse the last serialized bytes
  30. // NOTE that it is very important that nothing else calls saveKey with saveTo: false
  31. } else {
  32. lastEncodedValue = value;
  33. bytes = saveKey(value, this.writeKey, false, store.maxKeySize);
  34. }
  35. if (bytes.end > 0 && !(REUSE_BUFFER_MODE & mode)) {
  36. return bytes.subarray(bytes.start, bytes.end);
  37. }
  38. return bytes;
  39. };
  40. store.encoder.copyBuffers = true; // just an indicator for the buffer reuse in write.js
  41. }
  42. if (store.decoder && store.decoder.readKey && !store.decoder.decode) {
  43. store.decoder.decode = function(buffer) { return this.readKey(buffer, 0, buffer.length); };
  44. store.decoderCopies = true;
  45. }
  46. if (store.keyIsUint32 || store.keyEncoding == 'uint32') {
  47. store.writeKey = writeUint32Key;
  48. store.readKey = readUint32Key;
  49. } else if (store.keyIsBuffer || store.keyEncoding == 'binary') {
  50. store.writeKey = writeBufferKey;
  51. store.readKey = readBufferKey;
  52. } else if (store.keyEncoder) {
  53. store.writeKey = store.keyEncoder.writeKey;
  54. store.readKey = store.keyEncoder.readKey;
  55. } else {
  56. store.writeKey = orderedBinary.writeKey;
  57. store.readKey = orderedBinary.readKey;
  58. }
  59. }
  60. let saveBuffer, uint32, saveDataView = { setFloat64() {}, setUint32() {} }, saveDataAddress;
  61. let savePosition = 8000;
  62. let DYNAMIC_KEY_BUFFER_SIZE = 8192;
  63. function allocateSaveBuffer() {
  64. saveBuffer = typeof Buffer != 'undefined' ? Buffer.alloc(DYNAMIC_KEY_BUFFER_SIZE) : new Uint8Array(DYNAMIC_KEY_BUFFER_SIZE);
  65. uint32 = null;
  66. saveBuffer.buffer.address = getAddress(saveBuffer.buffer);
  67. saveDataAddress = saveBuffer.buffer.address;
  68. // TODO: Conditionally only do this for key sequences?
  69. saveDataView.setUint32(savePosition, 0xffffffff);
  70. saveDataView.setFloat64(savePosition + 4, saveDataAddress, true); // save a pointer from the old buffer to the new address for the sake of the prefetch sequences
  71. saveDataView = saveBuffer.dataView || (saveBuffer.dataView = new DataView(saveBuffer.buffer, saveBuffer.byteOffset, saveBuffer.byteLength));
  72. savePosition = 0;
  73. }
  74. export function saveKey(key, writeKey, saveTo, maxKeySize, flags) {
  75. if (savePosition > 7800) {
  76. allocateSaveBuffer();
  77. }
  78. let start = savePosition;
  79. try {
  80. savePosition = key === undefined ? start + 4 :
  81. writeKey(key, saveBuffer, start + 4);
  82. } catch (error) {
  83. saveBuffer.fill(0, start + 4); // restore zeros
  84. if (error.name == 'RangeError') {
  85. if (8180 - start < maxKeySize) {
  86. allocateSaveBuffer(); // try again:
  87. return saveKey(key, writeKey, saveTo, maxKeySize);
  88. }
  89. throw new Error('Key was too large, max key size is ' + maxKeySize);
  90. } else
  91. throw error;
  92. }
  93. let length = savePosition - start - 4;
  94. if (length > maxKeySize) {
  95. throw new Error('Key of size ' + length + ' was too large, max key size is ' + maxKeySize);
  96. }
  97. if (savePosition >= 8160) { // need to reserve enough room at the end for pointers
  98. savePosition = start // reset position
  99. allocateSaveBuffer(); // try again:
  100. return saveKey(key, writeKey, saveTo, maxKeySize);
  101. }
  102. if (saveTo) {
  103. saveDataView.setUint32(start, flags ? length | flags : length, true); // save the length
  104. saveTo.saveBuffer = saveBuffer;
  105. savePosition = (savePosition + 12) & 0xfffffc;
  106. return start + saveDataAddress;
  107. } else {
  108. saveBuffer.start = start + 4;
  109. saveBuffer.end = savePosition;
  110. savePosition = (savePosition + 7) & 0xfffff8; // full 64-bit word alignment since these are usually copied
  111. return saveBuffer;
  112. }
  113. }