index.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // @ts-check
  2. 'use strict'
  3. const assert = require('check-types').assert
  4. const Blob = require('../blob')
  5. // Dependencies are loaded at the bottom of the file to mitigate circular
  6. // dependency
  7. let BinaryFileData = null
  8. let HashFileData = null
  9. let HollowBinaryFileData = null
  10. let HollowStringFileData = null
  11. let LazyStringFileData = null
  12. let StringFileData = null
  13. /**
  14. * @typedef {import("../types").BlobStore} BlobStore
  15. * @typedef {import("../types").ReadonlyBlobStore} ReadonlyBlobStore
  16. * @typedef {import("../operation/edit_operation")} EditOperation
  17. * @typedef {import("../file_data/comment_list")} CommentList
  18. * @typedef {import("../types").CommentRawData} CommentRawData
  19. * @typedef {import("../file_data/tracked_change_list")} TrackedChangeList
  20. */
  21. /**
  22. * Helper to represent the content of a file. This class and its subclasses
  23. * should be used only through {@link File}.
  24. */
  25. class FileData {
  26. /** @see File.fromRaw */
  27. static fromRaw(raw) {
  28. if (Object.prototype.hasOwnProperty.call(raw, 'hash')) {
  29. if (Object.prototype.hasOwnProperty.call(raw, 'byteLength'))
  30. return BinaryFileData.fromRaw(raw)
  31. if (Object.prototype.hasOwnProperty.call(raw, 'stringLength'))
  32. return LazyStringFileData.fromRaw(raw)
  33. return HashFileData.fromRaw(raw)
  34. }
  35. if (Object.prototype.hasOwnProperty.call(raw, 'byteLength'))
  36. return HollowBinaryFileData.fromRaw(raw)
  37. if (Object.prototype.hasOwnProperty.call(raw, 'stringLength'))
  38. return HollowStringFileData.fromRaw(raw)
  39. if (Object.prototype.hasOwnProperty.call(raw, 'content'))
  40. return StringFileData.fromRaw(raw)
  41. throw new Error('FileData: bad raw object ' + JSON.stringify(raw))
  42. }
  43. /** @see File.createHollow */
  44. static createHollow(byteLength, stringLength) {
  45. if (stringLength == null) {
  46. return new HollowBinaryFileData(byteLength)
  47. }
  48. return new HollowStringFileData(stringLength)
  49. }
  50. /**
  51. * @see File.createLazyFromBlob
  52. * @param {Blob} blob
  53. * @param {Blob} [rangesBlob]
  54. */
  55. static createLazyFromBlobs(blob, rangesBlob) {
  56. assert.instance(blob, Blob, 'FileData: bad blob')
  57. if (blob.getStringLength() == null) {
  58. return new BinaryFileData(blob.getHash(), blob.getByteLength())
  59. }
  60. return new LazyStringFileData(
  61. blob.getHash(),
  62. rangesBlob?.getHash(),
  63. blob.getStringLength()
  64. )
  65. }
  66. toRaw() {
  67. throw new Error('FileData: toRaw not implemented')
  68. }
  69. /**
  70. * @see File#getHash
  71. * @return {string | null | undefined}
  72. */
  73. getHash() {
  74. return null
  75. }
  76. /**
  77. * @see File#getHash
  78. * @return {string | null | undefined}
  79. */
  80. getRangesHash() {
  81. return null
  82. }
  83. /**
  84. * @see File#getContent
  85. * @param {import('../file').FileGetContentOptions} [opts]
  86. * @return {string | null | undefined}
  87. */
  88. getContent(opts = {}) {
  89. return null
  90. }
  91. /**
  92. * @see File#isEditable
  93. * @return {boolean | null | undefined} null if it is not currently known
  94. */
  95. isEditable() {
  96. return null
  97. }
  98. /**
  99. * @see File#getByteLength
  100. * @return {number | null | undefined}
  101. */
  102. getByteLength() {
  103. return null
  104. }
  105. /**
  106. * @see File#getStringLength
  107. * @return {number | null | undefined}
  108. */
  109. getStringLength() {
  110. return null
  111. }
  112. /**
  113. * @see File#edit
  114. * @param {EditOperation} editOperation
  115. */
  116. edit(editOperation) {
  117. throw new Error('edit not implemented for ' + JSON.stringify(this))
  118. }
  119. /**
  120. * @function
  121. * @param {ReadonlyBlobStore} blobStore
  122. * @return {Promise<FileData>}
  123. * @abstract
  124. * @see FileData#load
  125. */
  126. async toEager(blobStore) {
  127. throw new Error('toEager not implemented for ' + JSON.stringify(this))
  128. }
  129. /**
  130. * @function
  131. * @param {ReadonlyBlobStore} blobStore
  132. * @return {Promise<FileData>}
  133. * @abstract
  134. * @see FileData#load
  135. */
  136. async toLazy(blobStore) {
  137. throw new Error('toLazy not implemented for ' + JSON.stringify(this))
  138. }
  139. /**
  140. * @function
  141. * @param {ReadonlyBlobStore} blobStore
  142. * @return {Promise<FileData>}
  143. * @abstract
  144. * @see FileData#load
  145. */
  146. async toHollow(blobStore) {
  147. throw new Error('toHollow not implemented for ' + JSON.stringify(this))
  148. }
  149. /**
  150. * @see File#load
  151. * @param {string} kind
  152. * @param {ReadonlyBlobStore} blobStore
  153. * @return {Promise<FileData>}
  154. */
  155. async load(kind, blobStore) {
  156. if (kind === 'eager') return await this.toEager(blobStore)
  157. if (kind === 'lazy') return await this.toLazy(blobStore)
  158. if (kind === 'hollow') return await this.toHollow(blobStore)
  159. throw new Error('bad file data load kind: ' + kind)
  160. }
  161. /**
  162. * @see File#store
  163. * @function
  164. * @param {BlobStore} blobStore
  165. * @return {Promise<Object>} a raw HashFile
  166. * @abstract
  167. */
  168. async store(blobStore) {
  169. throw new Error('store not implemented for ' + JSON.stringify(this))
  170. }
  171. /**
  172. * @see File#getComments
  173. * @function
  174. * @return {CommentList}
  175. * @abstract
  176. */
  177. getComments() {
  178. throw new Error('getComments not implemented for ' + JSON.stringify(this))
  179. }
  180. /**
  181. * @see File#getTrackedChanges
  182. * @function
  183. * @return {TrackedChangeList}
  184. * @abstract
  185. */
  186. getTrackedChanges() {
  187. throw new Error(
  188. 'getTrackedChanges not implemented for ' + JSON.stringify(this)
  189. )
  190. }
  191. }
  192. module.exports = FileData
  193. BinaryFileData = require('./binary_file_data')
  194. HashFileData = require('./hash_file_data')
  195. HollowBinaryFileData = require('./hollow_binary_file_data')
  196. HollowStringFileData = require('./hollow_string_file_data')
  197. LazyStringFileData = require('./lazy_string_file_data')
  198. StringFileData = require('./string_file_data')