@yume-chan/adb 0.0.16 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/CHANGELOG.json +18 -0
  2. package/CHANGELOG.md +13 -1
  3. package/LICENSE +1 -1
  4. package/esm/adb.d.ts +13 -8
  5. package/esm/adb.d.ts.map +1 -1
  6. package/esm/adb.js +63 -38
  7. package/esm/adb.js.map +1 -1
  8. package/esm/auth.d.ts +4 -4
  9. package/esm/auth.d.ts.map +1 -1
  10. package/esm/auth.js +6 -6
  11. package/esm/auth.js.map +1 -1
  12. package/esm/backend.d.ts +3 -3
  13. package/esm/backend.d.ts.map +1 -1
  14. package/esm/commands/base.d.ts +2 -2
  15. package/esm/commands/base.d.ts.map +1 -1
  16. package/esm/commands/base.js +1 -1
  17. package/esm/commands/base.js.map +1 -1
  18. package/esm/commands/framebuffer.d.ts +22 -6
  19. package/esm/commands/framebuffer.d.ts.map +1 -1
  20. package/esm/commands/framebuffer.js +33 -45
  21. package/esm/commands/framebuffer.js.map +1 -1
  22. package/esm/commands/install.d.ts +2 -2
  23. package/esm/commands/install.d.ts.map +1 -1
  24. package/esm/commands/install.js +12 -5
  25. package/esm/commands/install.js.map +1 -1
  26. package/esm/commands/power.d.ts.map +1 -1
  27. package/esm/commands/power.js +13 -9
  28. package/esm/commands/power.js.map +1 -1
  29. package/esm/commands/reverse.d.ts +5 -5
  30. package/esm/commands/reverse.d.ts.map +1 -1
  31. package/esm/commands/reverse.js +20 -18
  32. package/esm/commands/reverse.js.map +1 -1
  33. package/esm/commands/subprocess/command.d.ts +52 -0
  34. package/esm/commands/subprocess/command.d.ts.map +1 -0
  35. package/esm/commands/subprocess/command.js +81 -0
  36. package/esm/commands/subprocess/command.js.map +1 -0
  37. package/esm/commands/subprocess/index.d.ts +1 -53
  38. package/esm/commands/subprocess/index.d.ts.map +1 -1
  39. package/esm/commands/subprocess/index.js +1 -85
  40. package/esm/commands/subprocess/index.js.map +1 -1
  41. package/esm/commands/subprocess/protocols/none.d.ts +5 -5
  42. package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
  43. package/esm/commands/subprocess/protocols/none.js +5 -3
  44. package/esm/commands/subprocess/protocols/none.js.map +1 -1
  45. package/esm/commands/subprocess/protocols/shell.d.ts +4 -4
  46. package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
  47. package/esm/commands/subprocess/protocols/shell.js +28 -20
  48. package/esm/commands/subprocess/protocols/shell.js.map +1 -1
  49. package/esm/commands/subprocess/protocols/types.d.ts +7 -7
  50. package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
  51. package/esm/commands/sync/index.d.ts +1 -1
  52. package/esm/commands/sync/index.d.ts.map +1 -1
  53. package/esm/commands/sync/index.js +1 -1
  54. package/esm/commands/sync/index.js.map +1 -1
  55. package/esm/commands/sync/list.d.ts +7 -7
  56. package/esm/commands/sync/list.d.ts.map +1 -1
  57. package/esm/commands/sync/list.js +34 -50
  58. package/esm/commands/sync/list.js.map +1 -1
  59. package/esm/commands/sync/pull.d.ts +5 -4
  60. package/esm/commands/sync/pull.d.ts.map +1 -1
  61. package/esm/commands/sync/pull.js +21 -22
  62. package/esm/commands/sync/pull.js.map +1 -1
  63. package/esm/commands/sync/push.d.ts +4 -4
  64. package/esm/commands/sync/push.d.ts.map +1 -1
  65. package/esm/commands/sync/push.js +7 -11
  66. package/esm/commands/sync/push.js.map +1 -1
  67. package/esm/commands/sync/request.d.ts +4 -4
  68. package/esm/commands/sync/request.d.ts.map +1 -1
  69. package/esm/commands/sync/request.js +6 -6
  70. package/esm/commands/sync/request.js.map +1 -1
  71. package/esm/commands/sync/response.d.ts +5 -10
  72. package/esm/commands/sync/response.d.ts.map +1 -1
  73. package/esm/commands/sync/response.js +35 -26
  74. package/esm/commands/sync/response.js.map +1 -1
  75. package/esm/commands/sync/stat.d.ts +7 -7
  76. package/esm/commands/sync/stat.d.ts.map +1 -1
  77. package/esm/commands/sync/stat.js +48 -55
  78. package/esm/commands/sync/stat.js.map +1 -1
  79. package/esm/commands/sync/sync.d.ts +7 -7
  80. package/esm/commands/sync/sync.d.ts.map +1 -1
  81. package/esm/commands/sync/sync.js +25 -22
  82. package/esm/commands/sync/sync.js.map +1 -1
  83. package/esm/crypto.d.ts.map +1 -1
  84. package/esm/crypto.js +26 -16
  85. package/esm/crypto.js.map +1 -1
  86. package/esm/index.d.ts +9 -10
  87. package/esm/index.d.ts.map +1 -1
  88. package/esm/index.js +9 -10
  89. package/esm/index.js.map +1 -1
  90. package/esm/packet.d.ts +8 -8
  91. package/esm/packet.d.ts.map +1 -1
  92. package/esm/packet.js +14 -12
  93. package/esm/packet.js.map +1 -1
  94. package/esm/socket/dispatcher.d.ts +11 -6
  95. package/esm/socket/dispatcher.d.ts.map +1 -1
  96. package/esm/socket/dispatcher.js +28 -20
  97. package/esm/socket/dispatcher.js.map +1 -1
  98. package/esm/socket/index.d.ts +1 -1
  99. package/esm/socket/index.d.ts.map +1 -1
  100. package/esm/socket/index.js +1 -1
  101. package/esm/socket/index.js.map +1 -1
  102. package/esm/socket/socket.d.ts +5 -5
  103. package/esm/socket/socket.d.ts.map +1 -1
  104. package/esm/socket/socket.js +37 -17
  105. package/esm/socket/socket.js.map +1 -1
  106. package/esm/utils/auto-reset-event.d.ts +1 -1
  107. package/esm/utils/auto-reset-event.d.ts.map +1 -1
  108. package/esm/utils/auto-reset-event.js +2 -2
  109. package/esm/utils/base64.d.ts +23 -0
  110. package/esm/utils/base64.d.ts.map +1 -1
  111. package/esm/utils/base64.js +36 -29
  112. package/esm/utils/base64.js.map +1 -1
  113. package/package.json +19 -17
  114. package/src/adb.ts +140 -86
  115. package/src/auth.ts +27 -18
  116. package/src/backend.ts +7 -4
  117. package/src/commands/base.ts +3 -2
  118. package/src/commands/framebuffer.ts +48 -47
  119. package/src/commands/install.ts +20 -10
  120. package/src/commands/power.ts +14 -10
  121. package/src/commands/reverse.ts +53 -33
  122. package/src/commands/subprocess/command.ts +134 -0
  123. package/src/commands/subprocess/index.ts +1 -137
  124. package/src/commands/subprocess/protocols/none.ts +10 -6
  125. package/src/commands/subprocess/protocols/shell.ts +72 -39
  126. package/src/commands/subprocess/protocols/types.ts +12 -8
  127. package/src/commands/sync/index.ts +1 -1
  128. package/src/commands/sync/list.ts +63 -68
  129. package/src/commands/sync/pull.ts +53 -37
  130. package/src/commands/sync/push.ts +26 -15
  131. package/src/commands/sync/request.ts +20 -21
  132. package/src/commands/sync/response.ts +63 -53
  133. package/src/commands/sync/stat.ts +91 -90
  134. package/src/commands/sync/sync.ts +56 -34
  135. package/src/crypto.ts +61 -33
  136. package/src/features.ts +1 -1
  137. package/src/index.ts +9 -11
  138. package/src/packet.ts +40 -30
  139. package/src/socket/dispatcher.ts +119 -77
  140. package/src/socket/index.ts +1 -1
  141. package/src/socket/socket.ts +68 -26
  142. package/src/utils/auto-reset-event.ts +3 -3
  143. package/src/utils/base64.ts +75 -42
  144. package/tsconfig.build.json +1 -1
  145. package/tsconfig.build.tsbuildinfo +1 -1
  146. package/esm/stream/buffered.d.ts +0 -39
  147. package/esm/stream/buffered.d.ts.map +0 -1
  148. package/esm/stream/buffered.js +0 -143
  149. package/esm/stream/buffered.js.map +0 -1
  150. package/esm/stream/detect.d.ts +0 -2
  151. package/esm/stream/detect.d.ts.map +0 -1
  152. package/esm/stream/detect.js +0 -6
  153. package/esm/stream/detect.js.map +0 -1
  154. package/esm/stream/detect.native.d.ts +0 -240
  155. package/esm/stream/detect.native.d.ts.map +0 -1
  156. package/esm/stream/detect.native.js +0 -60
  157. package/esm/stream/detect.native.js.map +0 -1
  158. package/esm/stream/detect.polyfill.d.ts +0 -18
  159. package/esm/stream/detect.polyfill.d.ts.map +0 -1
  160. package/esm/stream/detect.polyfill.js +0 -4
  161. package/esm/stream/detect.polyfill.js.map +0 -1
  162. package/esm/stream/index.d.ts +0 -4
  163. package/esm/stream/index.d.ts.map +0 -1
  164. package/esm/stream/index.js +0 -4
  165. package/esm/stream/index.js.map +0 -1
  166. package/esm/stream/transform.d.ts +0 -124
  167. package/esm/stream/transform.d.ts.map +0 -1
  168. package/esm/stream/transform.js +0 -379
  169. package/esm/stream/transform.js.map +0 -1
  170. package/src/stream/buffered.ts +0 -168
  171. package/src/stream/detect.native.ts +0 -362
  172. package/src/stream/detect.polyfill.ts +0 -22
  173. package/src/stream/detect.ts +0 -7
  174. package/src/stream/index.ts +0 -3
  175. package/src/stream/transform.ts +0 -474
  176. package/tsconfig.test.json +0 -9
  177. package/web-streams-polyfill-4.0.0-beta.2.tgz +0 -0
@@ -1,11 +1,23 @@
1
- import { PromiseResolver } from "@yume-chan/async";
2
- import Struct, { placeholder, type StructValueType } from "@yume-chan/struct";
3
- import type { Adb } from "../../../adb.js";
4
- import { AdbFeatures } from "../../../features.js";
5
- import type { AdbSocket } from "../../../socket/index.js";
6
- import { pipeFrom, PushReadableStream, ReadableStream, StructDeserializeStream, StructSerializeStream, TransformStream, WritableStream, WritableStreamDefaultWriter, type PushReadableStreamController } from "../../../stream/index.js";
7
- import { encodeUtf8 } from "../../../utils/index.js";
8
- import type { AdbSubprocessProtocol } from "./types.js";
1
+ import { PromiseResolver } from '@yume-chan/async';
2
+ import {
3
+ PushReadableStream,
4
+ StructDeserializeStream,
5
+ StructSerializeStream,
6
+ TransformStream,
7
+ WritableStream,
8
+ pipeFrom,
9
+ type PushReadableStreamController,
10
+ type ReadableStream,
11
+ type WritableStreamDefaultWriter,
12
+ } from "@yume-chan/stream-extra";
13
+ import Struct, { placeholder, type StructValueType } from '@yume-chan/struct';
14
+
15
+ import { type Adb } from "../../../adb.js";
16
+ import { AdbFeatures } from '../../../features.js';
17
+ import { type AdbSocket } from "../../../socket/index.js";
18
+ import { encodeUtf8 } from '../../../utils/index.js';
19
+
20
+ import { type AdbSubprocessProtocol } from "./types.js";
9
21
 
10
22
  export enum AdbShellProtocolId {
11
23
  Stdin,
@@ -55,15 +67,17 @@ class StdoutDeserializeStream extends TransformStream<AdbShellProtocolPacket, Ui
55
67
  }
56
68
  }
57
69
 
58
- class MultiplexStream<T>{
70
+ class MultiplexStream<T> {
59
71
  private _readable: PushReadableStream<T>;
60
72
  private _readableController!: PushReadableStreamController<T>;
61
- public get readable() { return this._readable; }
73
+ public get readable() {
74
+ return this._readable;
75
+ }
62
76
 
63
77
  private _activeCount = 0;
64
78
 
65
79
  constructor() {
66
- this._readable = new PushReadableStream(controller => {
80
+ this._readable = new PushReadableStream((controller) => {
67
81
  this._readableController = controller;
68
82
  });
69
83
  }
@@ -76,13 +90,13 @@ class MultiplexStream<T>{
76
90
  write: async (chunk) => {
77
91
  await this._readableController.enqueue(chunk);
78
92
  },
79
- abort: async (e) => {
93
+ abort: () => {
80
94
  this._activeCount -= 1;
81
95
  if (this._activeCount === 0) {
82
96
  this._readableController.close();
83
97
  }
84
98
  },
85
- close: async () => {
99
+ close: () => {
86
100
  this._activeCount -= 1;
87
101
  if (this._activeCount === 0) {
88
102
  this._readableController.close();
@@ -102,32 +116,44 @@ class MultiplexStream<T>{
102
116
  */
103
117
  export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
104
118
  public static isSupported(adb: Adb) {
105
- return adb.features!.includes(AdbFeatures.ShellV2);
119
+ return adb.features.includes(AdbFeatures.ShellV2);
106
120
  }
107
121
 
108
122
  public static async pty(adb: Adb, command: string) {
109
123
  // TODO: AdbShellSubprocessProtocol: Support setting `XTERM` environment variable
110
- return new AdbSubprocessShellProtocol(await adb.createSocket(`shell,v2,pty:${command}`));
124
+ return new AdbSubprocessShellProtocol(
125
+ await adb.createSocket(`shell,v2,pty:${command}`)
126
+ );
111
127
  }
112
128
 
113
129
  public static async raw(adb: Adb, command: string) {
114
- return new AdbSubprocessShellProtocol(await adb.createSocket(`shell,v2,raw:${command}`));
130
+ return new AdbSubprocessShellProtocol(
131
+ await adb.createSocket(`shell,v2,raw:${command}`)
132
+ );
115
133
  }
116
134
 
117
135
  private readonly _socket: AdbSocket;
118
136
  private _socketWriter: WritableStreamDefaultWriter<AdbShellProtocolPacketInit>;
119
137
 
120
138
  private _stdin: WritableStream<Uint8Array>;
121
- public get stdin() { return this._stdin; }
139
+ public get stdin() {
140
+ return this._stdin;
141
+ }
122
142
 
123
143
  private _stdout: ReadableStream<Uint8Array>;
124
- public get stdout() { return this._stdout; }
144
+ public get stdout() {
145
+ return this._stdout;
146
+ }
125
147
 
126
148
  private _stderr: ReadableStream<Uint8Array>;
127
- public get stderr() { return this._stderr; }
149
+ public get stderr() {
150
+ return this._stderr;
151
+ }
128
152
 
129
153
  private readonly _exit = new PromiseResolver<number>();
130
- public get exit() { return this._exit.promise; }
154
+ public get exit() {
155
+ return this._exit.promise;
156
+ }
131
157
 
132
158
  public constructor(socket: AdbSocket) {
133
159
  this._socket = socket;
@@ -140,27 +166,34 @@ export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
140
166
 
141
167
  const [stdout, stderr] = socket.readable
142
168
  .pipeThrough(new StructDeserializeStream(AdbShellProtocolPacket))
143
- .pipeThrough(new TransformStream<AdbShellProtocolPacket, AdbShellProtocolPacket>({
144
- transform: (chunk, controller) => {
145
- if (chunk.id === AdbShellProtocolId.Exit) {
146
- this._exit.resolve(new Uint8Array(chunk.data)[0]!);
147
- // We can let `StdoutDeserializeStream` to process `AdbShellProtocolId.Exit`,
148
- // but since we need this `TransformStream` to capture the exit code anyway,
149
- // terminating child streams here is killing two birds with one stone.
150
- controller.terminate();
151
- return;
152
- }
153
- controller.enqueue(chunk);
154
- }
155
- }))
169
+ .pipeThrough(
170
+ new TransformStream<
171
+ AdbShellProtocolPacket,
172
+ AdbShellProtocolPacket
173
+ >({
174
+ transform: (chunk, controller) => {
175
+ if (chunk.id === AdbShellProtocolId.Exit) {
176
+ this._exit.resolve(new Uint8Array(chunk.data)[0]!);
177
+ // We can let `StdoutDeserializeStream` to process `AdbShellProtocolId.Exit`,
178
+ // but since we need this `TransformStream` to capture the exit code anyway,
179
+ // terminating child streams here is killing two birds with one stone.
180
+ controller.terminate();
181
+ return;
182
+ }
183
+ controller.enqueue(chunk);
184
+ },
185
+ })
186
+ )
156
187
  .tee();
157
- this._stdout = stdout
158
- .pipeThrough(new StdoutDeserializeStream(AdbShellProtocolId.Stdout));
159
- this._stderr = stderr
160
- .pipeThrough(new StdoutDeserializeStream(AdbShellProtocolId.Stderr));
188
+ this._stdout = stdout.pipeThrough(
189
+ new StdoutDeserializeStream(AdbShellProtocolId.Stdout)
190
+ );
191
+ this._stderr = stderr.pipeThrough(
192
+ new StdoutDeserializeStream(AdbShellProtocolId.Stderr)
193
+ );
161
194
 
162
195
  const multiplexer = new MultiplexStream<AdbShellProtocolPacketInit>();
163
- multiplexer.readable
196
+ void multiplexer.readable
164
197
  .pipeThrough(new StructSerializeStream(AdbShellProtocolPacket))
165
198
  .pipeTo(socket.writable);
166
199
 
@@ -178,7 +211,7 @@ export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
178
211
  data: encodeUtf8(
179
212
  // The "correct" format is `${rows}x${cols},${x_pixels}x${y_pixels}`
180
213
  // However, according to https://linux.die.net/man/4/tty_ioctl
181
- // `x_pixels` and `y_pixels` are not used, so always passing `0` is fine.
214
+ // `x_pixels` and `y_pixels` are unused, so always sending `0` should be fine.
182
215
  `${rows}x${cols},0x0\0`
183
216
  ),
184
217
  });
@@ -1,21 +1,25 @@
1
- import type { ValueOrPromise } from "@yume-chan/struct";
2
- import type { Adb } from "../../../adb.js";
3
- import type { AdbSocket } from "../../../socket/index.js";
4
- import type { ReadableStream, WritableStream } from "../../../stream/index.js";
1
+ import {
2
+ type ReadableStream,
3
+ type WritableStream,
4
+ } from "@yume-chan/stream-extra";
5
+ import { type ValueOrPromise } from "@yume-chan/struct";
6
+
7
+ import { type Adb } from "../../../adb.js";
8
+ import { type AdbSocket } from "../../../socket/index.js";
5
9
 
6
10
  export interface AdbSubprocessProtocol {
7
11
  /**
8
- * A WritableStream that writes to the `stdin` pipe.
12
+ * A WritableStream that writes to the `stdin` stream.
9
13
  */
10
14
  readonly stdin: WritableStream<Uint8Array>;
11
15
 
12
16
  /**
13
- * The `stdout` pipe of the process.
17
+ * The `stdout` stream of the process.
14
18
  */
15
19
  readonly stdout: ReadableStream<Uint8Array>;
16
20
 
17
21
  /**
18
- * The `stderr` pipe of the process.
22
+ * The `stderr` stream of the process.
19
23
  *
20
24
  * Note: Some `AdbSubprocessProtocol` doesn't separate `stdout` and `stderr`,
21
25
  * All output will be sent to `stdout`.
@@ -55,5 +59,5 @@ export interface AdbSubprocessProtocolConstructor {
55
59
  raw(adb: Adb, command: string): ValueOrPromise<AdbSubprocessProtocol>;
56
60
 
57
61
  /** Creates a new `AdbShell` by attaching to an exist `AdbSocket` */
58
- new(socket: AdbSocket): AdbSubprocessProtocol;
62
+ new (socket: AdbSocket): AdbSubprocessProtocol;
59
63
  }
@@ -1,7 +1,7 @@
1
1
  export * from './list.js';
2
2
  export * from './pull.js';
3
+ export * from './push.js';
3
4
  export * from './request.js';
4
5
  export * from './response.js';
5
- export * from './push.js';
6
6
  export * from './stat.js';
7
7
  export * from './sync.js';
@@ -1,86 +1,81 @@
1
- import Struct from '@yume-chan/struct';
2
- import type { AdbBufferedStream, WritableStreamDefaultWriter } from '../../stream/index.js';
3
- import { AdbSyncRequestId, adbSyncWriteRequest } from './request.js';
4
- import { AdbSyncDoneResponse, adbSyncReadResponse, AdbSyncResponseId } from './response.js';
5
- import { AdbSyncLstatResponse, AdbSyncStatResponse, type AdbSyncStat } from './stat.js';
1
+ import {
2
+ type BufferedReadableStream,
3
+ type WritableStreamDefaultWriter,
4
+ } from "@yume-chan/stream-extra";
5
+ import Struct from "@yume-chan/struct";
6
+
7
+ import { AdbSyncRequestId, adbSyncWriteRequest } from "./request.js";
8
+ import { AdbSyncResponseId, adbSyncReadResponses } from "./response.js";
9
+ import {
10
+ AdbSyncLstatResponse,
11
+ AdbSyncStatResponse,
12
+ type AdbSyncStat,
13
+ } from "./stat.js";
6
14
 
7
15
  export interface AdbSyncEntry extends AdbSyncStat {
8
16
  name: string;
9
17
  }
10
18
 
11
- export const AdbSyncEntryResponse =
12
- new Struct({ littleEndian: true })
13
- .fields(AdbSyncLstatResponse)
14
- .uint32('nameLength')
15
- .string('name', { lengthField: 'nameLength' })
16
- .extra({ id: AdbSyncResponseId.Entry as const });
17
-
18
- export type AdbSyncEntryResponse = typeof AdbSyncEntryResponse['TDeserializeResult'];
19
+ export const AdbSyncEntryResponse = new Struct({ littleEndian: true })
20
+ .fields(AdbSyncLstatResponse)
21
+ .uint32("nameLength")
22
+ .string("name", { lengthField: "nameLength" })
23
+ .extra({ id: AdbSyncResponseId.Entry as const });
19
24
 
20
- export const AdbSyncEntry2Response =
21
- new Struct({ littleEndian: true })
22
- .fields(AdbSyncStatResponse)
23
- .uint32('nameLength')
24
- .string('name', { lengthField: 'nameLength' })
25
- .extra({ id: AdbSyncResponseId.Entry2 as const });
25
+ export type AdbSyncEntryResponse =
26
+ typeof AdbSyncEntryResponse["TDeserializeResult"];
26
27
 
27
- export type AdbSyncEntry2Response = typeof AdbSyncEntry2Response['TDeserializeResult'];
28
+ export const AdbSyncEntry2Response = new Struct({ littleEndian: true })
29
+ .fields(AdbSyncStatResponse)
30
+ .uint32("nameLength")
31
+ .string("name", { lengthField: "nameLength" })
32
+ .extra({ id: AdbSyncResponseId.Entry2 as const });
28
33
 
29
- const LIST_V1_RESPONSE_TYPES = {
30
- [AdbSyncResponseId.Entry]: AdbSyncEntryResponse,
31
- [AdbSyncResponseId.Done]: new AdbSyncDoneResponse(AdbSyncEntryResponse.size),
32
- };
33
-
34
- const LIST_V2_RESPONSE_TYPES = {
35
- [AdbSyncResponseId.Entry2]: AdbSyncEntry2Response,
36
- [AdbSyncResponseId.Done]: new AdbSyncDoneResponse(AdbSyncEntry2Response.size),
37
- };
34
+ export type AdbSyncEntry2Response =
35
+ typeof AdbSyncEntry2Response["TDeserializeResult"];
38
36
 
39
37
  export async function* adbSyncOpenDir(
40
- stream: AdbBufferedStream,
38
+ stream: BufferedReadableStream,
41
39
  writer: WritableStreamDefaultWriter<Uint8Array>,
42
40
  path: string,
43
- v2: boolean,
41
+ v2: boolean
44
42
  ): AsyncGenerator<AdbSyncEntry, void, void> {
45
- let requestId: AdbSyncRequestId.List | AdbSyncRequestId.List2;
46
- let responseType: typeof LIST_V1_RESPONSE_TYPES | typeof LIST_V2_RESPONSE_TYPES;
47
-
48
43
  if (v2) {
49
- requestId = AdbSyncRequestId.List2;
50
- responseType = LIST_V2_RESPONSE_TYPES;
44
+ await adbSyncWriteRequest(writer, AdbSyncRequestId.List2, path);
45
+ for await (const item of adbSyncReadResponses(
46
+ stream,
47
+ AdbSyncResponseId.Entry2,
48
+ AdbSyncEntry2Response
49
+ )) {
50
+ // `LST2` can return error codes for failed `lstat` calls.
51
+ // `LIST` just ignores them.
52
+ // But they only contain `name` so still pretty useless.
53
+ if (item.error !== 0) {
54
+ continue;
55
+ }
56
+ yield item;
57
+ }
51
58
  } else {
52
- requestId = AdbSyncRequestId.List;
53
- responseType = LIST_V1_RESPONSE_TYPES;
54
- }
55
-
56
- await adbSyncWriteRequest(writer, requestId, path);
57
-
58
- while (true) {
59
- const response = await adbSyncReadResponse(stream, responseType);
60
- switch (response.id) {
61
- case AdbSyncResponseId.Entry:
62
- yield {
63
- mode: response.mode,
64
- size: BigInt(response.size),
65
- mtime: BigInt(response.mtime),
66
- get type() { return response.type; },
67
- get permission() { return response.permission; },
68
- name: response.name,
69
- };
70
- break;
71
- case AdbSyncResponseId.Entry2:
72
- // `LST2` can return error codes for failed `lstat` calls.
73
- // `LIST` just ignores them.
74
- // But they only contain `name` so still pretty useless.
75
- if (response.error !== 0) {
76
- continue;
77
- }
78
- yield response;
79
- break;
80
- case AdbSyncResponseId.Done:
81
- return;
82
- default:
83
- throw new Error('Unexpected response id');
59
+ await adbSyncWriteRequest(writer, AdbSyncRequestId.List, path);
60
+ for await (const item of adbSyncReadResponses(
61
+ stream,
62
+ AdbSyncResponseId.Entry,
63
+ AdbSyncEntryResponse
64
+ )) {
65
+ // Convert to same format as `AdbSyncEntry2Response` for easier consumption.
66
+ // However it will add some overhead.
67
+ yield {
68
+ mode: item.mode,
69
+ size: BigInt(item.size),
70
+ mtime: BigInt(item.mtime),
71
+ get type() {
72
+ return item.type;
73
+ },
74
+ get permission() {
75
+ return item.permission;
76
+ },
77
+ name: item.name,
78
+ };
84
79
  }
85
80
  }
86
81
  }
@@ -1,46 +1,62 @@
1
- import Struct from '@yume-chan/struct';
2
- import { AdbBufferedStream, ReadableStream, WritableStreamDefaultWriter } from '../../stream/index.js';
3
- import { AdbSyncRequestId, adbSyncWriteRequest } from './request.js';
4
- import { AdbSyncDoneResponse, adbSyncReadResponse, AdbSyncResponseId } from './response.js';
1
+ import {
2
+ ReadableStream,
3
+ type BufferedReadableStream,
4
+ type WritableStreamDefaultWriter,
5
+ } from "@yume-chan/stream-extra";
6
+ import Struct from "@yume-chan/struct";
5
7
 
6
- export const AdbSyncDataResponse =
7
- new Struct({ littleEndian: true })
8
- .uint32('dataLength')
9
- .uint8Array('data', { lengthField: 'dataLength' })
10
- .extra({ id: AdbSyncResponseId.Data as const });
8
+ import { AdbSyncRequestId, adbSyncWriteRequest } from "./request.js";
9
+ import { AdbSyncResponseId, adbSyncReadResponses } from "./response.js";
11
10
 
12
- const RESPONSE_TYPES = {
13
- [AdbSyncResponseId.Data]: AdbSyncDataResponse,
14
- [AdbSyncResponseId.Done]: new AdbSyncDoneResponse(AdbSyncDataResponse.size),
15
- };
11
+ export const AdbSyncDataResponse = new Struct({ littleEndian: true })
12
+ .uint32("dataLength")
13
+ .uint8Array("data", { lengthField: "dataLength" })
14
+ .extra({ id: AdbSyncResponseId.Data as const });
15
+
16
+ export type AdbSyncDataResponse =
17
+ typeof AdbSyncDataResponse["TDeserializeResult"];
16
18
 
17
19
  export function adbSyncPull(
18
- stream: AdbBufferedStream,
20
+ stream: BufferedReadableStream,
19
21
  writer: WritableStreamDefaultWriter<Uint8Array>,
20
- path: string,
22
+ path: string
21
23
  ): ReadableStream<Uint8Array> {
22
- return new ReadableStream<Uint8Array>({
23
- async start() {
24
- await adbSyncWriteRequest(writer, AdbSyncRequestId.Receive, path);
25
- },
26
- async pull(controller) {
27
- const response = await adbSyncReadResponse(stream, RESPONSE_TYPES);
28
- switch (response.id) {
29
- case AdbSyncResponseId.Data:
30
- controller.enqueue(response.data!);
31
- break;
32
- case AdbSyncResponseId.Done:
24
+ let generator!: AsyncGenerator<AdbSyncDataResponse, void, void>;
25
+ return new ReadableStream<Uint8Array>(
26
+ {
27
+ async start() {
28
+ // TODO: If `ReadableStream.from(AsyncGenerator)` is added to spec, use it instead.
29
+ await adbSyncWriteRequest(
30
+ writer,
31
+ AdbSyncRequestId.Receive,
32
+ path
33
+ );
34
+ generator = adbSyncReadResponses(
35
+ stream,
36
+ AdbSyncResponseId.Data,
37
+ AdbSyncDataResponse
38
+ );
39
+ },
40
+ async pull(controller) {
41
+ const { done, value } = await generator.next();
42
+ if (done) {
33
43
  controller.close();
34
- break;
35
- default:
36
- throw new Error('Unexpected response id');
37
- }
38
- },
39
- cancel() {
40
- throw new Error(`Sync commands don't support cancel.`);
44
+ return;
45
+ }
46
+ controller.enqueue(value.data);
47
+ },
48
+ cancel() {
49
+ generator.return().catch((e) => {
50
+ void e;
51
+ });
52
+ throw new Error(`Sync commands can't be canceled.`);
53
+ },
41
54
  },
42
- }, {
43
- highWaterMark: 16 * 1024,
44
- size(chunk) { return chunk.byteLength; }
45
- });
55
+ {
56
+ highWaterMark: 16 * 1024,
57
+ size(chunk) {
58
+ return chunk.byteLength;
59
+ },
60
+ }
61
+ );
46
62
  }
@@ -1,39 +1,50 @@
1
- import Struct from '@yume-chan/struct';
2
- import { AdbBufferedStream, ChunkStream, pipeFrom, WritableStream, WritableStreamDefaultWriter } from '../../stream/index.js';
3
- import { AdbSyncRequestId, adbSyncWriteRequest } from './request.js';
4
- import { adbSyncReadResponse, AdbSyncResponseId } from './response.js';
5
- import { LinuxFileType } from './stat.js';
1
+ import {
2
+ ChunkStream,
3
+ WritableStream,
4
+ pipeFrom,
5
+ type BufferedReadableStream,
6
+ type WritableStreamDefaultWriter,
7
+ } from "@yume-chan/stream-extra";
8
+ import Struct from "@yume-chan/struct";
6
9
 
7
- export const AdbSyncOkResponse =
8
- new Struct({ littleEndian: true })
9
- .uint32('unused');
10
+ import { AdbSyncRequestId, adbSyncWriteRequest } from "./request.js";
11
+ import { AdbSyncResponseId, adbSyncReadResponse } from "./response.js";
12
+ import { LinuxFileType } from "./stat.js";
10
13
 
11
- const ResponseTypes = {
12
- [AdbSyncResponseId.Ok]: AdbSyncOkResponse,
13
- };
14
+ export const AdbSyncOkResponse = new Struct({ littleEndian: true }).uint32(
15
+ "unused"
16
+ );
14
17
 
15
18
  export const ADB_SYNC_MAX_PACKET_SIZE = 64 * 1024;
16
19
 
17
20
  export function adbSyncPush(
18
- stream: AdbBufferedStream,
21
+ stream: BufferedReadableStream,
19
22
  writer: WritableStreamDefaultWriter<Uint8Array>,
20
23
  filename: string,
21
24
  mode: number = (LinuxFileType.File << 12) | 0o666,
22
25
  mtime: number = (Date.now() / 1000) | 0,
23
- packetSize: number = ADB_SYNC_MAX_PACKET_SIZE,
26
+ packetSize: number = ADB_SYNC_MAX_PACKET_SIZE
24
27
  ): WritableStream<Uint8Array> {
25
28
  return pipeFrom(
26
29
  new WritableStream<Uint8Array>({
27
30
  async start() {
28
31
  const pathAndMode = `${filename},${mode.toString()}`;
29
- await adbSyncWriteRequest(writer, AdbSyncRequestId.Send, pathAndMode);
32
+ await adbSyncWriteRequest(
33
+ writer,
34
+ AdbSyncRequestId.Send,
35
+ pathAndMode
36
+ );
30
37
  },
31
38
  async write(chunk) {
32
39
  await adbSyncWriteRequest(writer, AdbSyncRequestId.Data, chunk);
33
40
  },
34
41
  async close() {
35
42
  await adbSyncWriteRequest(writer, AdbSyncRequestId.Done, mtime);
36
- await adbSyncReadResponse(stream, ResponseTypes);
43
+ await adbSyncReadResponse(
44
+ stream,
45
+ AdbSyncResponseId.Ok,
46
+ AdbSyncOkResponse
47
+ );
37
48
  },
38
49
  }),
39
50
  new ChunkStream(packetSize)
@@ -1,28 +1,27 @@
1
- import Struct from '@yume-chan/struct';
2
- import type { WritableStreamDefaultWriter } from "../../stream/index.js";
1
+ import { type WritableStreamDefaultWriter } from "@yume-chan/stream-extra";
2
+ import Struct from "@yume-chan/struct";
3
+
3
4
  import { encodeUtf8 } from "../../utils/index.js";
4
5
 
5
6
  export enum AdbSyncRequestId {
6
- List = 'LIST',
7
- List2 = 'LIS2',
8
- Send = 'SEND',
9
- Lstat = 'STAT',
10
- Stat = 'STA2',
11
- Lstat2 = 'LST2',
12
- Data = 'DATA',
13
- Done = 'DONE',
14
- Receive = 'RECV',
7
+ List = "LIST",
8
+ List2 = "LIS2",
9
+ Send = "SEND",
10
+ Lstat = "STAT",
11
+ Stat = "STA2",
12
+ Lstat2 = "LST2",
13
+ Data = "DATA",
14
+ Done = "DONE",
15
+ Receive = "RECV",
15
16
  }
16
17
 
17
- export const AdbSyncNumberRequest =
18
- new Struct({ littleEndian: true })
19
- .string('id', { length: 4 })
20
- .uint32('arg');
18
+ export const AdbSyncNumberRequest = new Struct({ littleEndian: true })
19
+ .string("id", { length: 4 })
20
+ .uint32("arg");
21
21
 
22
- export const AdbSyncDataRequest =
23
- new Struct({ littleEndian: true })
24
- .fields(AdbSyncNumberRequest)
25
- .uint8Array('data', { lengthField: 'arg' });
22
+ export const AdbSyncDataRequest = new Struct({ littleEndian: true })
23
+ .fields(AdbSyncNumberRequest)
24
+ .uint8Array("data", { lengthField: "arg" });
26
25
 
27
26
  export async function adbSyncWriteRequest(
28
27
  writer: WritableStreamDefaultWriter<Uint8Array>,
@@ -30,12 +29,12 @@ export async function adbSyncWriteRequest(
30
29
  value: number | string | Uint8Array
31
30
  ): Promise<void> {
32
31
  let buffer: Uint8Array;
33
- if (typeof value === 'number') {
32
+ if (typeof value === "number") {
34
33
  buffer = AdbSyncNumberRequest.serialize({
35
34
  id,
36
35
  arg: value,
37
36
  });
38
- } else if (typeof value === 'string') {
37
+ } else if (typeof value === "string") {
39
38
  buffer = AdbSyncDataRequest.serialize({
40
39
  id,
41
40
  data: encodeUtf8(value),