blob.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // Copyright 2011 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Mock blob object.
  16. *
  17. */
  18. goog.setTestOnly('goog.testing.fs.Blob');
  19. goog.provide('goog.testing.fs.Blob');
  20. goog.require('goog.crypt');
  21. goog.require('goog.crypt.base64');
  22. /**
  23. * A mock Blob object. The data is stored as an Array of bytes, a "byte" being a
  24. * JS number in the range 0-255.
  25. *
  26. * This blob simplifies writing test code because it has the toString() method
  27. * that returns immediately, while the File API only provides asynchronous
  28. * reads.
  29. * @see https://www.w3.org/TR/FileAPI/#constructorBlob
  30. *
  31. * @param {(string|Array<(string|number|!Uint8Array)>)=} opt_data The data
  32. * encapsulated by the blob.
  33. * @param {string=} opt_type The mime type of the blob.
  34. * @constructor
  35. */
  36. goog.testing.fs.Blob = function(opt_data, opt_type) {
  37. /**
  38. * @see http://www.w3.org/TR/FileAPI/#dfn-type
  39. * @type {string}
  40. */
  41. this.type = opt_type || '';
  42. /**
  43. * The data encapsulated by the blob as an Array of bytes, a "byte" being a
  44. * JS number in the range 0-255.
  45. * @private {!Array<number>}
  46. */
  47. this.data_ = [];
  48. /**
  49. * @see http://www.w3.org/TR/FileAPI/#dfn-size
  50. * @type {number}
  51. */
  52. this.size = 0;
  53. this.setDataInternal(opt_data || '');
  54. };
  55. /**
  56. * Creates a blob with bytes of a blob ranging from the optional start
  57. * parameter up to but not including the optional end parameter, and with a type
  58. * attribute that is the value of the optional contentType parameter.
  59. * @see http://www.w3.org/TR/FileAPI/#dfn-slice
  60. * @param {number=} opt_start The start byte offset.
  61. * @param {number=} opt_end The end point of a slice.
  62. * @param {string=} opt_contentType The type of the resulting Blob.
  63. * @return {!goog.testing.fs.Blob} The result blob of the slice operation.
  64. */
  65. goog.testing.fs.Blob.prototype.slice = function(
  66. opt_start, opt_end, opt_contentType) {
  67. var relativeStart;
  68. if (goog.isNumber(opt_start)) {
  69. relativeStart = (opt_start < 0) ? Math.max(this.size + opt_start, 0) :
  70. Math.min(opt_start, this.size);
  71. } else {
  72. relativeStart = 0;
  73. }
  74. var relativeEnd;
  75. if (goog.isNumber(opt_end)) {
  76. relativeEnd = (opt_end < 0) ? Math.max(this.size + opt_end, 0) :
  77. Math.min(opt_end, this.size);
  78. } else {
  79. relativeEnd = this.size;
  80. }
  81. var span = Math.max(relativeEnd - relativeStart, 0);
  82. var blob = new goog.testing.fs.Blob(
  83. this.data_.slice(relativeStart, relativeStart + span), opt_contentType);
  84. return blob;
  85. };
  86. /**
  87. * @return {string} The data encapsulated by the blob as an UTF-8 string.
  88. * @override
  89. */
  90. goog.testing.fs.Blob.prototype.toString = function() {
  91. return goog.crypt.utf8ByteArrayToString(this.data_);
  92. };
  93. /**
  94. * @return {!ArrayBuffer} The data encapsulated by the blob as an
  95. * ArrayBuffer.
  96. */
  97. goog.testing.fs.Blob.prototype.toArrayBuffer = function() {
  98. var buf = new ArrayBuffer(this.data_.length);
  99. var arr = new Uint8Array(buf);
  100. for (var i = 0; i < this.data_.length; i++) {
  101. arr[i] = this.data_[i];
  102. }
  103. return buf;
  104. };
  105. /**
  106. * @return {string} The string data encapsulated by the blob as a data: URI.
  107. */
  108. goog.testing.fs.Blob.prototype.toDataUrl = function() {
  109. return 'data:' + this.type + ';base64,' +
  110. goog.crypt.base64.encodeByteArray(this.data_);
  111. };
  112. /**
  113. * Sets the internal contents of the blob to an Array of bytes. This should
  114. * only be called by other functions inside the {@code goog.testing.fs}
  115. * namespace.
  116. * @param {string|Array<string|number|!Uint8Array>} data The data to write
  117. * into the blob.
  118. * @package
  119. */
  120. goog.testing.fs.Blob.prototype.setDataInternal = function(data) {
  121. this.data_ = [];
  122. if (typeof data === 'string') {
  123. this.appendString_(data);
  124. } else if (data instanceof Array) {
  125. for (var i = 0; i < data.length; i++) {
  126. if (typeof data[i] === 'string') {
  127. this.appendString_(data[i]);
  128. } else if (typeof data[i] === 'number') { // Assume Bytes array.
  129. this.appendByte_(data[i]);
  130. } else if (data[i] instanceof Uint8Array) {
  131. this.appendUint8_(data[i]);
  132. }
  133. }
  134. }
  135. this.size = this.data_.length;
  136. };
  137. /**
  138. * Converts the data from string to Array of bytes and appends to the blob
  139. * content.
  140. * @param {string} data The string to append to the blob content.
  141. * @private
  142. */
  143. goog.testing.fs.Blob.prototype.appendString_ = function(data) {
  144. Array.prototype.push.apply(
  145. this.data_, goog.crypt.stringToUtf8ByteArray(data));
  146. };
  147. /**
  148. * Appends a byte (as a number between 0 to 255) to the blob content.
  149. * @param {number} data The byte to append.
  150. * @private
  151. */
  152. goog.testing.fs.Blob.prototype.appendByte_ = function(data) {
  153. this.data_.push(data);
  154. };
  155. /**
  156. * Converts the data from Uint8Array to Array of bytes and appends it to the
  157. * blob content.
  158. * @param {!Uint8Array} data The array to append to the blob content.
  159. * @private
  160. */
  161. goog.testing.fs.Blob.prototype.appendUint8_ = function(data) {
  162. for (var i = 0; i < data.length; i++) {
  163. this.data_.push(data[i]);
  164. }
  165. };