Repositorio del curso CCOM4030 el semestre B91 del proyecto Artesanías con el Instituto de Cultura

serializer.js 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. (function (global, factory) {
  2. if (typeof define === "function" && define.amd) {
  3. define('localforageSerializer', ['module', 'exports', './createBlob'], factory);
  4. } else if (typeof exports !== "undefined") {
  5. factory(module, exports, require('./createBlob'));
  6. } else {
  7. var mod = {
  8. exports: {}
  9. };
  10. factory(mod, mod.exports, global.createBlob);
  11. global.localforageSerializer = mod.exports;
  12. }
  13. })(this, function (module, exports, _createBlob) {
  14. 'use strict';
  15. Object.defineProperty(exports, "__esModule", {
  16. value: true
  17. });
  18. var _createBlob2 = _interopRequireDefault(_createBlob);
  19. function _interopRequireDefault(obj) {
  20. return obj && obj.__esModule ? obj : {
  21. default: obj
  22. };
  23. }
  24. // Sadly, the best way to save binary data in WebSQL/localStorage is serializing
  25. // it to Base64, so this is how we store it to prevent very strange errors with less
  26. // verbose ways of binary <-> string data storage.
  27. var BASE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; /* eslint-disable no-bitwise */
  28. var BLOB_TYPE_PREFIX = '~~local_forage_type~';
  29. var BLOB_TYPE_PREFIX_REGEX = /^~~local_forage_type~([^~]+)~/;
  30. var SERIALIZED_MARKER = '__lfsc__:';
  31. var SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER.length;
  32. // OMG the serializations!
  33. var TYPE_ARRAYBUFFER = 'arbf';
  34. var TYPE_BLOB = 'blob';
  35. var TYPE_INT8ARRAY = 'si08';
  36. var TYPE_UINT8ARRAY = 'ui08';
  37. var TYPE_UINT8CLAMPEDARRAY = 'uic8';
  38. var TYPE_INT16ARRAY = 'si16';
  39. var TYPE_INT32ARRAY = 'si32';
  40. var TYPE_UINT16ARRAY = 'ur16';
  41. var TYPE_UINT32ARRAY = 'ui32';
  42. var TYPE_FLOAT32ARRAY = 'fl32';
  43. var TYPE_FLOAT64ARRAY = 'fl64';
  44. var TYPE_SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER_LENGTH + TYPE_ARRAYBUFFER.length;
  45. var toString = Object.prototype.toString;
  46. function stringToBuffer(serializedString) {
  47. // Fill the string into a ArrayBuffer.
  48. var bufferLength = serializedString.length * 0.75;
  49. var len = serializedString.length;
  50. var i;
  51. var p = 0;
  52. var encoded1, encoded2, encoded3, encoded4;
  53. if (serializedString[serializedString.length - 1] === '=') {
  54. bufferLength--;
  55. if (serializedString[serializedString.length - 2] === '=') {
  56. bufferLength--;
  57. }
  58. }
  59. var buffer = new ArrayBuffer(bufferLength);
  60. var bytes = new Uint8Array(buffer);
  61. for (i = 0; i < len; i += 4) {
  62. encoded1 = BASE_CHARS.indexOf(serializedString[i]);
  63. encoded2 = BASE_CHARS.indexOf(serializedString[i + 1]);
  64. encoded3 = BASE_CHARS.indexOf(serializedString[i + 2]);
  65. encoded4 = BASE_CHARS.indexOf(serializedString[i + 3]);
  66. /*jslint bitwise: true */
  67. bytes[p++] = encoded1 << 2 | encoded2 >> 4;
  68. bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;
  69. bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;
  70. }
  71. return buffer;
  72. }
  73. // Converts a buffer to a string to store, serialized, in the backend
  74. // storage library.
  75. function bufferToString(buffer) {
  76. // base64-arraybuffer
  77. var bytes = new Uint8Array(buffer);
  78. var base64String = '';
  79. var i;
  80. for (i = 0; i < bytes.length; i += 3) {
  81. /*jslint bitwise: true */
  82. base64String += BASE_CHARS[bytes[i] >> 2];
  83. base64String += BASE_CHARS[(bytes[i] & 3) << 4 | bytes[i + 1] >> 4];
  84. base64String += BASE_CHARS[(bytes[i + 1] & 15) << 2 | bytes[i + 2] >> 6];
  85. base64String += BASE_CHARS[bytes[i + 2] & 63];
  86. }
  87. if (bytes.length % 3 === 2) {
  88. base64String = base64String.substring(0, base64String.length - 1) + '=';
  89. } else if (bytes.length % 3 === 1) {
  90. base64String = base64String.substring(0, base64String.length - 2) + '==';
  91. }
  92. return base64String;
  93. }
  94. // Serialize a value, afterwards executing a callback (which usually
  95. // instructs the `setItem()` callback/promise to be executed). This is how
  96. // we store binary data with localStorage.
  97. function serialize(value, callback) {
  98. var valueType = '';
  99. if (value) {
  100. valueType = toString.call(value);
  101. }
  102. // Cannot use `value instanceof ArrayBuffer` or such here, as these
  103. // checks fail when running the tests using casper.js...
  104. //
  105. // TODO: See why those tests fail and use a better solution.
  106. if (value && (valueType === '[object ArrayBuffer]' || value.buffer && toString.call(value.buffer) === '[object ArrayBuffer]')) {
  107. // Convert binary arrays to a string and prefix the string with
  108. // a special marker.
  109. var buffer;
  110. var marker = SERIALIZED_MARKER;
  111. if (value instanceof ArrayBuffer) {
  112. buffer = value;
  113. marker += TYPE_ARRAYBUFFER;
  114. } else {
  115. buffer = value.buffer;
  116. if (valueType === '[object Int8Array]') {
  117. marker += TYPE_INT8ARRAY;
  118. } else if (valueType === '[object Uint8Array]') {
  119. marker += TYPE_UINT8ARRAY;
  120. } else if (valueType === '[object Uint8ClampedArray]') {
  121. marker += TYPE_UINT8CLAMPEDARRAY;
  122. } else if (valueType === '[object Int16Array]') {
  123. marker += TYPE_INT16ARRAY;
  124. } else if (valueType === '[object Uint16Array]') {
  125. marker += TYPE_UINT16ARRAY;
  126. } else if (valueType === '[object Int32Array]') {
  127. marker += TYPE_INT32ARRAY;
  128. } else if (valueType === '[object Uint32Array]') {
  129. marker += TYPE_UINT32ARRAY;
  130. } else if (valueType === '[object Float32Array]') {
  131. marker += TYPE_FLOAT32ARRAY;
  132. } else if (valueType === '[object Float64Array]') {
  133. marker += TYPE_FLOAT64ARRAY;
  134. } else {
  135. callback(new Error('Failed to get type for BinaryArray'));
  136. }
  137. }
  138. callback(marker + bufferToString(buffer));
  139. } else if (valueType === '[object Blob]') {
  140. // Conver the blob to a binaryArray and then to a string.
  141. var fileReader = new FileReader();
  142. fileReader.onload = function () {
  143. // Backwards-compatible prefix for the blob type.
  144. var str = BLOB_TYPE_PREFIX + value.type + '~' + bufferToString(this.result);
  145. callback(SERIALIZED_MARKER + TYPE_BLOB + str);
  146. };
  147. fileReader.readAsArrayBuffer(value);
  148. } else {
  149. try {
  150. callback(JSON.stringify(value));
  151. } catch (e) {
  152. console.error("Couldn't convert value into a JSON string: ", value);
  153. callback(null, e);
  154. }
  155. }
  156. }
  157. // Deserialize data we've inserted into a value column/field. We place
  158. // special markers into our strings to mark them as encoded; this isn't
  159. // as nice as a meta field, but it's the only sane thing we can do whilst
  160. // keeping localStorage support intact.
  161. //
  162. // Oftentimes this will just deserialize JSON content, but if we have a
  163. // special marker (SERIALIZED_MARKER, defined above), we will extract
  164. // some kind of arraybuffer/binary data/typed array out of the string.
  165. function deserialize(value) {
  166. // If we haven't marked this string as being specially serialized (i.e.
  167. // something other than serialized JSON), we can just return it and be
  168. // done with it.
  169. if (value.substring(0, SERIALIZED_MARKER_LENGTH) !== SERIALIZED_MARKER) {
  170. return JSON.parse(value);
  171. }
  172. // The following code deals with deserializing some kind of Blob or
  173. // TypedArray. First we separate out the type of data we're dealing
  174. // with from the data itself.
  175. var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);
  176. var type = value.substring(SERIALIZED_MARKER_LENGTH, TYPE_SERIALIZED_MARKER_LENGTH);
  177. var blobType;
  178. // Backwards-compatible blob type serialization strategy.
  179. // DBs created with older versions of localForage will simply not have the blob type.
  180. if (type === TYPE_BLOB && BLOB_TYPE_PREFIX_REGEX.test(serializedString)) {
  181. var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX);
  182. blobType = matcher[1];
  183. serializedString = serializedString.substring(matcher[0].length);
  184. }
  185. var buffer = stringToBuffer(serializedString);
  186. // Return the right type based on the code/type set during
  187. // serialization.
  188. switch (type) {
  189. case TYPE_ARRAYBUFFER:
  190. return buffer;
  191. case TYPE_BLOB:
  192. return (0, _createBlob2.default)([buffer], { type: blobType });
  193. case TYPE_INT8ARRAY:
  194. return new Int8Array(buffer);
  195. case TYPE_UINT8ARRAY:
  196. return new Uint8Array(buffer);
  197. case TYPE_UINT8CLAMPEDARRAY:
  198. return new Uint8ClampedArray(buffer);
  199. case TYPE_INT16ARRAY:
  200. return new Int16Array(buffer);
  201. case TYPE_UINT16ARRAY:
  202. return new Uint16Array(buffer);
  203. case TYPE_INT32ARRAY:
  204. return new Int32Array(buffer);
  205. case TYPE_UINT32ARRAY:
  206. return new Uint32Array(buffer);
  207. case TYPE_FLOAT32ARRAY:
  208. return new Float32Array(buffer);
  209. case TYPE_FLOAT64ARRAY:
  210. return new Float64Array(buffer);
  211. default:
  212. throw new Error('Unkown type: ' + type);
  213. }
  214. }
  215. var localforageSerializer = {
  216. serialize: serialize,
  217. deserialize: deserialize,
  218. stringToBuffer: stringToBuffer,
  219. bufferToString: bufferToString
  220. };
  221. exports.default = localforageSerializer;
  222. module.exports = exports['default'];
  223. });