file.js 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import fs from 'fs';
  2. import { BaseSource } from './basesource.js';
  3. function closeAsync(fd) {
  4. return new Promise((resolve, reject) => {
  5. fs.close(fd, (err) => {
  6. if (err) {
  7. reject(err);
  8. } else {
  9. resolve();
  10. }
  11. });
  12. });
  13. }
  14. function openAsync(path, flags, mode = undefined) {
  15. return new Promise((resolve, reject) => {
  16. fs.open(path, flags, mode, (err, fd) => {
  17. if (err) {
  18. reject(err);
  19. } else {
  20. resolve(fd);
  21. }
  22. });
  23. });
  24. }
  25. function readAsync(...args) {
  26. return new Promise((resolve, reject) => {
  27. fs.read(...args, (err, bytesRead, buffer) => {
  28. if (err) {
  29. reject(err);
  30. } else {
  31. resolve({ bytesRead, buffer });
  32. }
  33. });
  34. });
  35. }
  36. class FileSource extends BaseSource {
  37. constructor(path) {
  38. super();
  39. this.path = path;
  40. this.openRequest = openAsync(path, 'r');
  41. }
  42. async fetchSlice(slice) {
  43. // TODO: use `signal`
  44. const fd = await this.openRequest;
  45. const { buffer } = await readAsync(
  46. fd,
  47. Buffer.alloc(slice.length),
  48. 0,
  49. slice.length,
  50. slice.offset,
  51. );
  52. return buffer.buffer;
  53. }
  54. async close() {
  55. const fd = await this.openRequest;
  56. await closeAsync(fd);
  57. }
  58. }
  59. export function makeFileSource(path) {
  60. return new FileSource(path);
  61. }