flexbuffers.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. var flexbuffers = {};
  2. flexbuffers.BinaryReader = class {
  3. static open(buffer) {
  4. const length = buffer.length;
  5. if (length >= 3) {
  6. const byteWidth = buffer[length - 1];
  7. if (byteWidth <= 8) {
  8. const packedType = buffer[length - 2];
  9. return new flexbuffers.BinaryReader(buffer, length - 2 - byteWidth, byteWidth, 1 << (packedType & 3), packedType >> 2);
  10. }
  11. }
  12. return null;
  13. }
  14. constructor(buffer, offset, parentWidth, byteWidth, type) {
  15. this._buffer = buffer;
  16. this._length = buffer.length;
  17. this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
  18. this._utf8Decoder = new TextDecoder('utf-8');
  19. this._root = new flexbuffers.Reference(this, offset, parentWidth, byteWidth, type);
  20. }
  21. read() {
  22. return this._root.read();
  23. }
  24. get length() {
  25. return this._length;
  26. }
  27. int(offset, size) {
  28. switch (size) {
  29. case 1: return this._view.getInt8(offset);
  30. case 2: return this._view.getInt16(offset, true);
  31. case 4: return this._view.getInt32(offset, true);
  32. case 8: return this._view.getInt64(offset, true);
  33. default: throw new flexbuffers.Error("Invalid int size '" + size + "'.");
  34. }
  35. }
  36. uint(offset, size) {
  37. switch (size) {
  38. case 1: return this._view.getUint8(offset);
  39. case 2: return this._view.getUint16(offset, true);
  40. case 4: return this._view.getUint32(offset, true);
  41. case 8: return this._view.getUint64(offset, true);
  42. default: throw new flexbuffers.Error("Invalid uint size '" + size + "'.");
  43. }
  44. }
  45. float(offset, size) {
  46. switch (size) {
  47. case 4: return this._view.getFloat32(offset, true);
  48. case 8: return this._view.getFloat64(offset, true);
  49. default: throw new flexbuffers.Error("Invalid float size '" + size + "'.");
  50. }
  51. }
  52. string(offset, size) {
  53. let end = size === undefined ? this._buffer.indexOf(0, offset) : offset + size;
  54. end = end === -1 ? this._buffer.length : end;
  55. const bytes = this._buffer.subarray(offset, end);
  56. return this._utf8Decoder.decode(bytes);
  57. }
  58. bytes(offset, size) {
  59. return this._buffer.slice(offset, offset + size);
  60. }
  61. };
  62. flexbuffers.Reference = class {
  63. constructor(reader, offset, parentWidth, byteWidth, type) {
  64. this._reader = reader;
  65. this._offset = offset;
  66. this._parentWidth = parentWidth;
  67. this._byteWidth = byteWidth;
  68. this._type = type;
  69. }
  70. read() {
  71. switch (this._type) {
  72. case 0x00: // null
  73. return null;
  74. case 0x01: // int
  75. return this._reader.int(this._offset, this._parentWidth);
  76. case 0x02: // uint
  77. return this._reader.uint(this._offset, this._parentWidth);
  78. case 0x03: // float
  79. return this._reader.float(this._offset, this._parentWidth);
  80. case 0x04: { // key
  81. return this._reader.string(this._indirect());
  82. }
  83. case 0x05: { // string
  84. const offset = this._indirect();
  85. const size = this._reader.uint(offset - this._byteWidth, this._byteWidth);
  86. return this._reader.string(offset, size);
  87. }
  88. case 0x06: // indirect int
  89. return this._reader.int(this._indirect(), this._byteWidth);
  90. case 0x07: // indirect uint
  91. return this._reader.uint(this._indirect(), this._byteWidth);
  92. case 0x08: // indirect float
  93. return this._reader.float(this._indirect(), this._byteWidth);
  94. case 0x09: { // map
  95. const offset = this._indirect();
  96. const keysOffset = offset - (this._byteWidth * 3);
  97. const keysVectorOffset = keysOffset - this._reader.uint(keysOffset, this._byteWidth);
  98. const keysByteWidth = this._reader.uint(keysOffset + this._byteWidth, this._byteWidth);
  99. const keys = this._typedVector(keysVectorOffset, keysByteWidth, 0x04);
  100. const values = this._vector(offset, this._byteWidth);
  101. const map = {};
  102. for (let i = 0; i < keys.length; i++) {
  103. map[keys[i]] = values[i];
  104. }
  105. return map;
  106. }
  107. case 0x0a: { // vector
  108. return this._vector(this._indirect(), this._byteWidth);
  109. }
  110. case 0x0b: // vector int
  111. case 0x0c: // vector uint
  112. case 0x0d: // vector float
  113. case 0x0e: // vector key
  114. case 0x0f: // vector string deprecated
  115. case 0x24: { // vector bool
  116. return this._typedVector(this._indirect(), this._byteWidth, this._type - 0x0b + 0x01);
  117. }
  118. case 0x10: // vector int2
  119. case 0x11: // vector uint2
  120. case 0x12: // vector float2
  121. case 0x13: // vector int3
  122. case 0x14: // vector uint3
  123. case 0x15: // vector float3
  124. case 0x16: // vector int4
  125. case 0x17: // vector uint4
  126. case 0x18: { // vector float4
  127. const offset = this._indirect();
  128. const size = (((this._type - 0x10) / 3) >> 0) + 2;
  129. const type = ((this._type - 0x10) % 3) + 0x01;
  130. return this._typedVector(offset, this._byteWidth, type, size);
  131. }
  132. case 0x19: { // blob
  133. const offset = this._indirect();
  134. const size = this._reader.uint(offset - this._byteWidth, this._byteWidth);
  135. return this._reader.bytes(offset, size);
  136. }
  137. case 0x1a: { // bool
  138. return this._reader.uint(this._offset, this._parentWidth) !== 0;
  139. }
  140. default: {
  141. throw new flexbuffers.Error("Unsupported reference type '" + this._type);
  142. }
  143. }
  144. }
  145. _indirect() {
  146. return this._offset - this._reader.uint(this._offset, this._parentWidth);
  147. }
  148. _vector(offset, byteWidth) {
  149. const size = this._reader.uint(offset - byteWidth, byteWidth);
  150. const packedTypeOffset = offset + (size * byteWidth);
  151. const vector = new Array(size);
  152. for (let i = 0; i < size; i++) {
  153. const packedType = this._reader.uint(packedTypeOffset + i, 1);
  154. const reference = new flexbuffers.Reference(this._reader, offset + (i * byteWidth), byteWidth, 1 << (packedType & 3), packedType >> 2);
  155. vector[i] = reference.read();
  156. }
  157. return vector;
  158. }
  159. _typedVector(offset, byteWidth, type, size) {
  160. size = size === undefined ? this._reader.uint(offset - byteWidth, byteWidth) : size;
  161. const vector = new Array(size);
  162. for (let i = 0; i < size; i++) {
  163. const reference = new flexbuffers.Reference(this._reader, offset + (i * byteWidth), byteWidth, 1, type);
  164. vector[i] = reference.read();
  165. }
  166. return vector;
  167. }
  168. };
  169. flexbuffers.Error = class extends Error {
  170. constructor(message) {
  171. super(message);
  172. this.name = 'FlexBuffers Error';
  173. this.message = message;
  174. }
  175. };
  176. if (typeof module !== 'undefined' && typeof module.exports === 'object') {
  177. module.exports.BinaryReader = flexbuffers.BinaryReader;
  178. }