summaryrefslogtreecommitdiff
path: root/js/io.ts
blob: 710722f42e2ca5fa19da6a02b3c42fef943bffe3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Interfaces 100% copied from Go.
// Documentation liberally lifted from them too.
// Thank you! We love Go!

// The bytes read during an I/O call and a boolean indicating EOF.
export interface ReadResult {
  nread: number;
  eof: boolean;
}

// Reader is the interface that wraps the basic read() method.
// https://golang.org/pkg/io/#Reader
export interface Reader {
  // read() reads up to p.byteLength bytes into p. It returns the number of
  // bytes read (0 <= n <= p.byteLength) and any error encountered. Even if
  // read() returns n < p.byteLength, it may use all of p as scratch space
  // during the call. If some data is available but not p.byteLength bytes,
  // read() conventionally returns what is available instead of waiting for
  // more.
  //
  // When read() encounters an error or end-of-file condition after successfully
  // reading n > 0 bytes, it returns the number of bytes read. It may return the
  // (non-nil) error from the same call or return the error (and n == 0) from a
  // subsequent call. An instance of this general case is that a Reader
  // returning a non-zero number of bytes at the end of the input stream may
  // return either err == EOF or err == nil. The next read() should return 0,
  // EOF.
  //
  // Callers should always process the n > 0 bytes returned before considering
  // the EOF. Doing so correctly handles I/O errors that happen after reading
  // some bytes and also both of the allowed EOF behaviors.
  //
  // Implementations of read() are discouraged from returning a zero byte count
  // with a nil error, except when p.byteLength == 0. Callers should treat a
  // return of 0 and nil as indicating that nothing happened; in particular it
  // does not indicate EOF.
  //
  // Implementations must not retain p.
  read(p: ArrayBufferView): Promise<ReadResult>;
}

// Writer is the interface that wraps the basic write() method.
// https://golang.org/pkg/io/#Writer
export interface Writer {
  // write() writes p.byteLength bytes from p to the underlying data stream. It
  // returns the number of bytes written from p (0 <= n <= p.byteLength) and any
  // error encountered that caused the write to stop early. write() must return
  // a non-nil error if it returns n < p.byteLength. write() must not modify the
  // slice data, even temporarily.
  //
  // Implementations must not retain p.
  write(p: ArrayBufferView): Promise<number>;
}

// https://golang.org/pkg/io/#Closer
export interface Closer {
  // The behavior of Close after the first call is undefined. Specific
  // implementations may document their own behavior.
  close(): void;
}

// https://golang.org/pkg/io/#Seeker
export interface Seeker {
  // Seek sets the offset for the next read() or write() to offset, interpreted
  // according to whence: SeekStart means relative to the start of the file,
  // SeekCurrent means relative to the current offset, and SeekEnd means
  // relative to the end. Seek returns the new offset relative to the start of
  // the file and an error, if any.
  //
  // Seeking to an offset before the start of the file is an error. Seeking to
  // any positive offset is legal, but the behavior of subsequent I/O operations
  // on the underlying object is implementation-dependent.
  seek(offset: number, whence: number): Promise<void>;
}

// https://golang.org/pkg/io/#ReadCloser
export interface ReaderCloser extends Reader, Closer {}

// https://golang.org/pkg/io/#WriteCloser
export interface WriteCloser extends Writer, Closer {}

// https://golang.org/pkg/io/#ReadSeeker
export interface ReadSeeker extends Reader, Seeker {}

// https://golang.org/pkg/io/#WriteSeeker
export interface WriteSeeker extends Writer, Seeker {}

// https://golang.org/pkg/io/#ReadWriteCloser
export interface ReadWriteCloser extends Reader, Writer, Closer {}

// https://golang.org/pkg/io/#ReadWriteSeeker
export interface ReadWriteSeeker extends Reader, Writer, Seeker {}

// copy() copies from src to dst until either EOF is reached on src or an error
// occurs. It returns the number of bytes copied and the first error encountered
// while copying, if any.
//
// Because copy() is defined to read from src until EOF, it does not treat an
// EOF from read() as an error to be reported.
//
// https://golang.org/pkg/io/#Copy
export async function copy(dst: Writer, src: Reader): Promise<number> {
  let n = 0;
  const b = new Uint8Array(1024);
  let gotEOF = false;
  while (gotEOF === false) {
    const result = await src.read(b);
    if (result.eof) {
      gotEOF = true;
    }
    n += await dst.write(b.subarray(0, result.nread));
  }
  return n;
}