@yume-chan/adb 0.0.17 → 0.0.19

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 +27 -0
  2. package/CHANGELOG.md +16 -1
  3. package/LICENSE +1 -1
  4. package/esm/adb.d.ts +63 -60
  5. package/esm/adb.d.ts.map +1 -1
  6. package/esm/adb.js +257 -229
  7. package/esm/adb.js.map +1 -1
  8. package/esm/auth.d.ts +51 -51
  9. package/esm/auth.d.ts.map +1 -1
  10. package/esm/auth.js +95 -96
  11. package/esm/auth.js.map +1 -1
  12. package/esm/backend.d.ts +8 -8
  13. package/esm/backend.d.ts.map +1 -1
  14. package/esm/backend.js +1 -1
  15. package/esm/commands/base.d.ts +6 -6
  16. package/esm/commands/base.js +8 -8
  17. package/esm/commands/framebuffer.d.ts +53 -53
  18. package/esm/commands/framebuffer.d.ts.map +1 -1
  19. package/esm/commands/framebuffer.js +46 -47
  20. package/esm/commands/framebuffer.js.map +1 -1
  21. package/esm/commands/index.d.ts +7 -8
  22. package/esm/commands/index.d.ts.map +1 -1
  23. package/esm/commands/index.js +7 -8
  24. package/esm/commands/index.js.map +1 -1
  25. package/esm/commands/install.d.ts +9 -3
  26. package/esm/commands/install.d.ts.map +1 -1
  27. package/esm/commands/install.js +27 -21
  28. package/esm/commands/install.js.map +1 -1
  29. package/esm/commands/power.d.ts +22 -22
  30. package/esm/commands/power.d.ts.map +1 -1
  31. package/esm/commands/power.js +48 -44
  32. package/esm/commands/power.js.map +1 -1
  33. package/esm/commands/reverse.d.ts +41 -28
  34. package/esm/commands/reverse.d.ts.map +1 -1
  35. package/esm/commands/reverse.js +125 -98
  36. package/esm/commands/reverse.js.map +1 -1
  37. package/esm/commands/subprocess/command.d.ts +57 -51
  38. package/esm/commands/subprocess/command.d.ts.map +1 -1
  39. package/esm/commands/subprocess/command.js +86 -82
  40. package/esm/commands/subprocess/command.js.map +1 -1
  41. package/esm/commands/subprocess/index.d.ts +3 -3
  42. package/esm/commands/subprocess/index.js +3 -3
  43. package/esm/commands/subprocess/protocols/index.d.ts +3 -3
  44. package/esm/commands/subprocess/protocols/index.js +3 -3
  45. package/esm/commands/subprocess/protocols/none.d.ts +35 -35
  46. package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
  47. package/esm/commands/subprocess/protocols/none.js +65 -55
  48. package/esm/commands/subprocess/protocols/none.js.map +1 -1
  49. package/esm/commands/subprocess/protocols/shell.d.ts +39 -38
  50. package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
  51. package/esm/commands/subprocess/protocols/shell.js +166 -154
  52. package/esm/commands/subprocess/protocols/shell.js.map +1 -1
  53. package/esm/commands/subprocess/protocols/types.d.ts +49 -49
  54. package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
  55. package/esm/commands/subprocess/protocols/types.js +1 -1
  56. package/esm/commands/subprocess/utils.d.ts +1 -1
  57. package/esm/commands/subprocess/utils.js +18 -18
  58. package/esm/commands/sync/index.d.ts +8 -7
  59. package/esm/commands/sync/index.d.ts.map +1 -1
  60. package/esm/commands/sync/index.js +8 -7
  61. package/esm/commands/sync/index.js.map +1 -1
  62. package/esm/commands/sync/list.d.ts +42 -40
  63. package/esm/commands/sync/list.d.ts.map +1 -1
  64. package/esm/commands/sync/list.js +67 -35
  65. package/esm/commands/sync/list.js.map +1 -1
  66. package/esm/commands/sync/pull.d.ts +13 -11
  67. package/esm/commands/sync/pull.d.ts.map +1 -1
  68. package/esm/commands/sync/pull.js +35 -36
  69. package/esm/commands/sync/pull.js.map +1 -1
  70. package/esm/commands/sync/push.d.ts +46 -7
  71. package/esm/commands/sync/push.d.ts.map +1 -1
  72. package/esm/commands/sync/push.js +89 -23
  73. package/esm/commands/sync/push.js.map +1 -1
  74. package/esm/commands/sync/request.d.ts +26 -23
  75. package/esm/commands/sync/request.d.ts.map +1 -1
  76. package/esm/commands/sync/request.js +40 -42
  77. package/esm/commands/sync/request.js.map +1 -1
  78. package/esm/commands/sync/response.d.ts +19 -19
  79. package/esm/commands/sync/response.d.ts.map +1 -1
  80. package/esm/commands/sync/response.js +54 -54
  81. package/esm/commands/sync/response.js.map +1 -1
  82. package/esm/commands/sync/socket.d.ts +27 -0
  83. package/esm/commands/sync/socket.d.ts.map +1 -0
  84. package/esm/commands/sync/socket.js +66 -0
  85. package/esm/commands/sync/socket.js.map +1 -0
  86. package/esm/commands/sync/stat.d.ts +72 -72
  87. package/esm/commands/sync/stat.d.ts.map +1 -1
  88. package/esm/commands/sync/stat.js +116 -94
  89. package/esm/commands/sync/stat.js.map +1 -1
  90. package/esm/commands/sync/sync.d.ts +72 -60
  91. package/esm/commands/sync/sync.d.ts.map +1 -1
  92. package/esm/commands/sync/sync.js +127 -148
  93. package/esm/commands/sync/sync.js.map +1 -1
  94. package/esm/commands/tcpip.d.ts +5 -5
  95. package/esm/commands/tcpip.js +18 -18
  96. package/esm/crypto.d.ts +36 -36
  97. package/esm/crypto.d.ts.map +1 -1
  98. package/esm/crypto.js +248 -238
  99. package/esm/crypto.js.map +1 -1
  100. package/esm/features.d.ts +10 -7
  101. package/esm/features.d.ts.map +1 -1
  102. package/esm/features.js +13 -10
  103. package/esm/features.js.map +1 -1
  104. package/esm/index.d.ts +9 -9
  105. package/esm/index.d.ts.map +1 -1
  106. package/esm/index.js +9 -9
  107. package/esm/index.js.map +1 -1
  108. package/esm/packet.d.ts +45 -46
  109. package/esm/packet.d.ts.map +1 -1
  110. package/esm/packet.js +43 -46
  111. package/esm/packet.js.map +1 -1
  112. package/esm/socket/dispatcher.d.ts +59 -59
  113. package/esm/socket/dispatcher.d.ts.map +1 -1
  114. package/esm/socket/dispatcher.js +223 -231
  115. package/esm/socket/dispatcher.js.map +1 -1
  116. package/esm/socket/index.d.ts +2 -2
  117. package/esm/socket/index.js +2 -2
  118. package/esm/socket/socket.d.ts +59 -59
  119. package/esm/socket/socket.d.ts.map +1 -1
  120. package/esm/socket/socket.js +118 -98
  121. package/esm/socket/socket.js.map +1 -1
  122. package/esm/utils/auto-reset-event.d.ts +9 -9
  123. package/esm/utils/auto-reset-event.d.ts.map +1 -1
  124. package/esm/utils/auto-reset-event.js +33 -33
  125. package/esm/utils/auto-reset-event.js.map +1 -1
  126. package/esm/utils/base64.d.ts +27 -27
  127. package/esm/utils/base64.d.ts.map +1 -1
  128. package/esm/utils/base64.js +246 -245
  129. package/esm/utils/base64.js.map +1 -1
  130. package/esm/utils/conditional-variable.d.ts +9 -0
  131. package/esm/utils/conditional-variable.d.ts.map +1 -0
  132. package/esm/utils/conditional-variable.js +34 -0
  133. package/esm/utils/conditional-variable.js.map +1 -0
  134. package/esm/utils/index.d.ts +4 -3
  135. package/esm/utils/index.d.ts.map +1 -1
  136. package/esm/utils/index.js +4 -3
  137. package/esm/utils/index.js.map +1 -1
  138. package/package.json +17 -13
  139. package/src/adb.ts +160 -101
  140. package/src/auth.ts +31 -22
  141. package/src/backend.ts +6 -4
  142. package/src/commands/base.ts +2 -2
  143. package/src/commands/framebuffer.ts +37 -41
  144. package/src/commands/index.ts +7 -8
  145. package/src/commands/power.ts +15 -11
  146. package/src/commands/reverse.ts +74 -30
  147. package/src/commands/subprocess/command.ts +34 -23
  148. package/src/commands/subprocess/index.ts +3 -3
  149. package/src/commands/subprocess/protocols/index.ts +3 -3
  150. package/src/commands/subprocess/protocols/none.ts +26 -11
  151. package/src/commands/subprocess/protocols/shell.ts +110 -56
  152. package/src/commands/subprocess/protocols/types.ts +10 -6
  153. package/src/commands/subprocess/utils.ts +1 -1
  154. package/src/commands/sync/index.ts +8 -7
  155. package/src/commands/sync/list.ts +74 -28
  156. package/src/commands/sync/pull.ts +49 -37
  157. package/src/commands/sync/push.ts +153 -32
  158. package/src/commands/sync/request.ts +37 -34
  159. package/src/commands/sync/response.ts +34 -27
  160. package/src/commands/sync/socket.ts +97 -0
  161. package/src/commands/sync/stat.ts +98 -70
  162. package/src/commands/sync/sync.ts +78 -97
  163. package/src/commands/tcpip.ts +5 -5
  164. package/src/crypto.ts +60 -32
  165. package/src/features.ts +9 -6
  166. package/src/index.ts +9 -10
  167. package/src/packet.ts +41 -46
  168. package/src/socket/dispatcher.ts +130 -108
  169. package/src/socket/index.ts +2 -2
  170. package/src/socket/socket.ts +84 -34
  171. package/src/utils/auto-reset-event.ts +16 -17
  172. package/src/utils/base64.ts +51 -41
  173. package/src/utils/conditional-variable.ts +45 -0
  174. package/src/utils/index.ts +4 -3
  175. package/tsconfig.build.json +1 -1
  176. package/tsconfig.build.tsbuildinfo +1 -1
  177. package/src/commands/install.ts +0 -32
@@ -1,11 +1,24 @@
1
- import { AsyncOperationManager, PromiseResolver } from '@yume-chan/async';
2
- import type { RemoveEventListener } from '@yume-chan/event';
3
- import { AbortController, WritableStream, WritableStreamDefaultWriter, type ReadableWritablePair } from '@yume-chan/stream-extra';
4
- import { EMPTY_UINT8_ARRAY, type ValueOrPromise } from '@yume-chan/struct';
5
-
6
- import { AdbCommand, calculateChecksum, type AdbPacketData, type AdbPacketInit } from '../packet.js';
7
- import { decodeUtf8, encodeUtf8 } from '../utils/index.js';
8
- import { AdbSocket, AdbSocketController } from './socket.js';
1
+ import { AsyncOperationManager, PromiseResolver } from "@yume-chan/async";
2
+ import type { RemoveEventListener } from "@yume-chan/event";
3
+ import type {
4
+ Consumable,
5
+ ReadableWritablePair,
6
+ WritableStreamDefaultWriter,
7
+ } from "@yume-chan/stream-extra";
8
+ import {
9
+ AbortController,
10
+ ConsumableWritableStream,
11
+ WritableStream,
12
+ } from "@yume-chan/stream-extra";
13
+ import type { ValueOrPromise } from "@yume-chan/struct";
14
+ import { EMPTY_UINT8_ARRAY } from "@yume-chan/struct";
15
+
16
+ import type { AdbPacketData, AdbPacketInit } from "../packet.js";
17
+ import { AdbCommand, calculateChecksum } from "../packet.js";
18
+ import { decodeUtf8, encodeUtf8 } from "../utils/index.js";
19
+
20
+ import type { AdbSocket } from "./socket.js";
21
+ import { AdbSocketController } from "./socket.js";
9
22
 
10
23
  export interface AdbPacketDispatcherOptions {
11
24
  calculateChecksum: boolean;
@@ -19,7 +32,9 @@ export interface AdbPacketDispatcherOptions {
19
32
  maxPayloadSize: number;
20
33
  }
21
34
 
22
- export type AdbIncomingSocketHandler = (socket: AdbSocket) => ValueOrPromise<boolean>;
35
+ export type AdbIncomingSocketHandler = (
36
+ socket: AdbSocket
37
+ ) => ValueOrPromise<boolean>;
23
38
 
24
39
  export interface Closeable {
25
40
  close(): ValueOrPromise<void>;
@@ -44,72 +59,92 @@ export class AdbPacketDispatcher implements Closeable {
44
59
  */
45
60
  private readonly sockets = new Map<number, AdbSocketController>();
46
61
 
47
- private _writer!: WritableStreamDefaultWriter<AdbPacketInit>;
62
+ private _writer: WritableStreamDefaultWriter<Consumable<AdbPacketInit>>;
48
63
 
49
64
  public readonly options: AdbPacketDispatcherOptions;
50
65
 
51
66
  private _closed = false;
52
67
  private _disconnected = new PromiseResolver<void>();
53
- public get disconnected() { return this._disconnected.promise; }
68
+ public get disconnected() {
69
+ return this._disconnected.promise;
70
+ }
54
71
 
55
72
  private _incomingSocketHandlers: Set<AdbIncomingSocketHandler> = new Set();
56
73
 
57
74
  private _abortController = new AbortController();
58
75
 
59
76
  public constructor(
60
- connection: ReadableWritablePair<AdbPacketData, AdbPacketInit>,
77
+ connection: ReadableWritablePair<
78
+ AdbPacketData,
79
+ Consumable<AdbPacketInit>
80
+ >,
61
81
  options: AdbPacketDispatcherOptions
62
82
  ) {
63
83
  this.options = options;
64
84
 
65
85
  connection.readable
66
- .pipeTo(new WritableStream({
67
- write: async (packet) => {
68
- switch (packet.command) {
69
- case AdbCommand.OK:
70
- this.handleOk(packet);
71
- break;
72
- case AdbCommand.Close:
73
- await this.handleClose(packet);
74
- break;
75
- case AdbCommand.Write:
76
- if (this.sockets.has(packet.arg1)) {
77
- await this.sockets.get(packet.arg1)!.enqueue(packet.payload);
78
- await this.sendPacket(AdbCommand.OK, packet.arg1, packet.arg0);
86
+ .pipeTo(
87
+ new WritableStream({
88
+ write: async (packet) => {
89
+ switch (packet.command) {
90
+ case AdbCommand.OK:
91
+ this.handleOk(packet);
79
92
  break;
80
- }
81
- throw new Error(`Unknown local socket id: ${packet.arg1}`);
82
- case AdbCommand.Open:
83
- await this.handleOpen(packet);
84
- break;
85
- default:
86
- // Junk data may only appear in the authentication phase,
87
- // since the dispatcher only works after authentication,
88
- // all packets should have a valid command.
89
- // (although it's possible that Adb added new commands in the future)
90
- throw new Error(`Unknown command: ${packet.command.toString(16)}`);
91
- }
93
+ case AdbCommand.Close:
94
+ await this.handleClose(packet);
95
+ break;
96
+ case AdbCommand.Write:
97
+ if (this.sockets.has(packet.arg1)) {
98
+ await this.sockets
99
+ .get(packet.arg1)!
100
+ .enqueue(packet.payload);
101
+ await this.sendPacket(
102
+ AdbCommand.OK,
103
+ packet.arg1,
104
+ packet.arg0
105
+ );
106
+ break;
107
+ }
108
+ throw new Error(
109
+ `Unknown local socket id: ${packet.arg1}`
110
+ );
111
+ case AdbCommand.Open:
112
+ await this.handleOpen(packet);
113
+ break;
114
+ default:
115
+ // Junk data may only appear in the authentication phase,
116
+ // since the dispatcher only works after authentication,
117
+ // all packets should have a valid command.
118
+ // (although it's possible that Adb added new commands in the future)
119
+ throw new Error(
120
+ `Unknown command: ${packet.command.toString(
121
+ 16
122
+ )}`
123
+ );
124
+ }
125
+ },
126
+ }),
127
+ {
128
+ // There are multiple reasons for the pipe to stop,
129
+ // (device disconnection, protocol error, or user abortion)
130
+ // if the underlying streams are still open,
131
+ // it's still possible to create another ADB connection.
132
+ // So don't close `readable` here.
133
+ preventCancel: true,
134
+ signal: this._abortController.signal,
135
+ }
136
+ )
137
+ .then(
138
+ () => {
139
+ this.dispose();
92
140
  },
93
- }), {
94
- // There are multiple reasons for the pipe to stop,
95
- // (device disconnection, protocol error, or user abortion)
96
- // if the underlying streams are still open,
97
- // it's still possible to create another ADB connection.
98
- // So don't close `readable` here.
99
- preventCancel: true,
100
- signal: this._abortController.signal,
101
- })
102
- .then(() => {
103
- this.dispose();
104
- }, (e) => {
105
- // https://github.com/MattiasBuelens/web-streams-polyfill/issues/115
106
- // `e` is always `AbortError` (instead of what I give in `abortController.abort()`)
107
- // so we can't check if `e` is a real error.
108
- if (!this._closed) {
109
- this._disconnected.reject(e);
141
+ (e) => {
142
+ if (!this._closed) {
143
+ this._disconnected.reject(e);
144
+ }
145
+ this.dispose();
110
146
  }
111
- this.dispose();
112
- });
147
+ );
113
148
 
114
149
  this._writer = connection.writable.getWriter();
115
150
  }
@@ -129,13 +164,18 @@ export class AdbPacketDispatcher implements Closeable {
129
164
 
130
165
  // Maybe the device is responding to a packet of last connection
131
166
  // Tell the device to close the socket
132
- this.sendPacket(AdbCommand.Close, packet.arg1, packet.arg0);
167
+ void this.sendPacket(AdbCommand.Close, packet.arg1, packet.arg0);
133
168
  }
134
169
 
135
170
  private async handleClose(packet: AdbPacketData) {
136
171
  // If the socket is still pending
137
- if (packet.arg0 === 0 &&
138
- this.initializers.reject(packet.arg1, new Error('Socket open failed'))) {
172
+ if (
173
+ packet.arg0 === 0 &&
174
+ this.initializers.reject(
175
+ packet.arg1,
176
+ new Error("Socket open failed")
177
+ )
178
+ ) {
139
179
  // Device failed to create the socket
140
180
  // (unknown service string, failed to execute command, etc.)
141
181
  // it doesn't break the connection,
@@ -156,9 +196,13 @@ export class AdbPacketDispatcher implements Closeable {
156
196
  if (socket) {
157
197
  // The device want to close the socket
158
198
  if (!socket.closed) {
159
- await this.sendPacket(AdbCommand.Close, packet.arg1, packet.arg0);
199
+ await this.sendPacket(
200
+ AdbCommand.Close,
201
+ packet.arg1,
202
+ packet.arg0
203
+ );
160
204
  }
161
- socket.dispose();
205
+ await socket.dispose();
162
206
  this.sockets.delete(packet.arg1);
163
207
  return;
164
208
  }
@@ -173,7 +217,9 @@ export class AdbPacketDispatcher implements Closeable {
173
217
  * @param handler A function to call with new incoming sockets. It must return `true` if it accepts the socket.
174
218
  * @returns A function to remove the handler.
175
219
  */
176
- public onIncomingSocket(handler: AdbIncomingSocketHandler): RemoveEventListener {
220
+ public onIncomingSocket(
221
+ handler: AdbIncomingSocketHandler
222
+ ): RemoveEventListener {
177
223
  this._incomingSocketHandlers.add(handler);
178
224
  const remove = () => {
179
225
  this._incomingSocketHandlers.delete(handler);
@@ -212,16 +258,11 @@ export class AdbPacketDispatcher implements Closeable {
212
258
 
213
259
  public async createSocket(serviceString: string): Promise<AdbSocket> {
214
260
  if (this.options.appendNullToServiceString) {
215
- serviceString += '\0';
261
+ serviceString += "\0";
216
262
  }
217
263
 
218
264
  const [localId, initializer] = this.initializers.add<number>();
219
- await this.sendPacket(
220
- AdbCommand.Open,
221
- localId,
222
- 0,
223
- serviceString
224
- );
265
+ await this.sendPacket(AdbCommand.Open, localId, 0, serviceString);
225
266
 
226
267
  // Fulfilled by `handleOk`
227
268
  const remoteId = await initializer;
@@ -237,57 +278,36 @@ export class AdbPacketDispatcher implements Closeable {
237
278
  return controller.socket;
238
279
  }
239
280
 
240
- public sendPacket(packet: AdbPacketInit): Promise<void>;
241
- public sendPacket(
281
+ public async sendPacket(
242
282
  command: AdbCommand,
243
283
  arg0: number,
244
284
  arg1: number,
245
- payload?: string | Uint8Array
246
- ): Promise<void>;
247
- public async sendPacket(
248
- packetOrCommand: AdbPacketInit | AdbCommand,
249
- arg0?: number,
250
- arg1?: number,
251
- payload: string | Uint8Array = EMPTY_UINT8_ARRAY,
285
+ payload: string | Uint8Array = EMPTY_UINT8_ARRAY
252
286
  ): Promise<void> {
253
- let init: AdbPacketData;
254
- if (arg0 === undefined) {
255
- init = packetOrCommand as AdbPacketInit;
256
- } else {
257
- if (typeof payload === 'string') {
258
- payload = encodeUtf8(payload);
259
- }
260
-
261
- init = {
262
- command: packetOrCommand as AdbCommand,
263
- arg0: arg0 as number,
264
- arg1: arg1 as number,
265
- payload,
266
- };
287
+ if (typeof payload === "string") {
288
+ payload = encodeUtf8(payload);
267
289
  }
268
290
 
269
- if (init.payload &&
270
- init.payload.byteLength > this.options.maxPayloadSize) {
271
- throw new Error('payload too large');
291
+ if (payload.byteLength > this.options.maxPayloadSize) {
292
+ throw new Error("payload too large");
272
293
  }
273
294
 
274
- if (this.options.calculateChecksum) {
275
- calculateChecksum(init);
276
- } else {
277
- (init as AdbPacketInit).checksum = 0;
278
- }
279
-
280
- await this._writer.ready;
281
- await this._writer.write(init as AdbPacketInit);
295
+ await ConsumableWritableStream.write(this._writer, {
296
+ command,
297
+ arg0,
298
+ arg1,
299
+ payload,
300
+ checksum: this.options.calculateChecksum
301
+ ? calculateChecksum(payload)
302
+ : 0,
303
+ magic: command ^ 0xffffffff,
304
+ });
282
305
  }
283
306
 
284
307
  public async close() {
285
308
  // Send `CLSE` packets for all sockets
286
309
  await Promise.all(
287
- Array.from(
288
- this.sockets.values(),
289
- socket => socket.close(),
290
- )
310
+ Array.from(this.sockets.values(), (socket) => socket.close())
291
311
  );
292
312
 
293
313
  // Stop receiving
@@ -302,7 +322,9 @@ export class AdbPacketDispatcher implements Closeable {
302
322
 
303
323
  private dispose() {
304
324
  for (const socket of this.sockets.values()) {
305
- socket.dispose();
325
+ socket.dispose().catch((e) => {
326
+ void e;
327
+ });
306
328
  }
307
329
 
308
330
  this._disconnected.resolve();
@@ -1,2 +1,2 @@
1
- export * from './dispatcher.js';
2
- export * from './socket.js';
1
+ export * from "./dispatcher.js";
2
+ export * from "./socket.js";
@@ -1,9 +1,23 @@
1
- import { PromiseResolver } from '@yume-chan/async';
2
- import type { Disposable } from '@yume-chan/event';
3
- import { ChunkStream, DuplexStreamFactory, pipeFrom, PushReadableStream, WritableStream, type PushReadableStreamController, type ReadableStream, type ReadableWritablePair } from '@yume-chan/stream-extra';
4
-
5
- import { AdbCommand } from '../packet.js';
6
- import type { AdbPacketDispatcher, Closeable } from './dispatcher.js';
1
+ import { PromiseResolver } from "@yume-chan/async";
2
+ import type { Disposable } from "@yume-chan/event";
3
+ import type {
4
+ Consumable,
5
+ PushReadableStreamController,
6
+ ReadableStream,
7
+ ReadableWritablePair,
8
+ WritableStream,
9
+ } from "@yume-chan/stream-extra";
10
+ import {
11
+ ConsumableWritableStream,
12
+ DistributionStream,
13
+ DuplexStreamFactory,
14
+ PushReadableStream,
15
+ pipeFrom,
16
+ } from "@yume-chan/stream-extra";
17
+
18
+ import { AdbCommand } from "../packet.js";
19
+
20
+ import type { AdbPacketDispatcher, Closeable } from "./dispatcher.js";
7
21
 
8
22
  export interface AdbSocketInfo {
9
23
  localId: number;
@@ -19,7 +33,13 @@ export interface AdbSocketConstructionOptions extends AdbSocketInfo {
19
33
  highWaterMark?: number | undefined;
20
34
  }
21
35
 
22
- export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<Uint8Array, Uint8Array>, Closeable, Disposable {
36
+ export class AdbSocketController
37
+ implements
38
+ AdbSocketInfo,
39
+ ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>,
40
+ Closeable,
41
+ Disposable
42
+ {
23
43
  private readonly dispatcher!: AdbPacketDispatcher;
24
44
 
25
45
  public readonly localId!: number;
@@ -27,14 +47,16 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
27
47
  public readonly localCreated!: boolean;
28
48
  public readonly serviceString!: string;
29
49
 
30
- private _duplex: DuplexStreamFactory<Uint8Array, Uint8Array>;
50
+ private _duplex: DuplexStreamFactory<Uint8Array, Consumable<Uint8Array>>;
31
51
 
32
52
  private _readable: ReadableStream<Uint8Array>;
33
53
  private _readableController!: PushReadableStreamController<Uint8Array>;
34
- public get readable() { return this._readable; }
54
+ public get readable() {
55
+ return this._readable;
56
+ }
35
57
 
36
58
  private _writePromise: PromiseResolver<void> | undefined;
37
- public readonly writable: WritableStream<Uint8Array>;
59
+ public readonly writable: WritableStream<Consumable<Uint8Array>>;
38
60
 
39
61
  private _closed = false;
40
62
  /**
@@ -42,10 +64,14 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
42
64
  *
43
65
  * It's only used by dispatcher to avoid sending another `CLSE` packet to remote.
44
66
  */
45
- public get closed() { return this._closed; }
67
+ public get closed() {
68
+ return this._closed;
69
+ }
46
70
 
47
71
  private _socket: AdbSocket;
48
- public get socket() { return this._socket; }
72
+ public get socket() {
73
+ return this._socket;
74
+ }
49
75
 
50
76
  public constructor(options: AdbSocketConstructionOptions) {
51
77
  Object.assign(this, options);
@@ -54,7 +80,10 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
54
80
  // cspell: disable-next-line
55
81
  // https://www.plantuml.com/plantuml/png/TL0zoeGm4ErpYc3l5JxyS0yWM6mX5j4C6p4cxcJ25ejttuGX88ZftizxUKmJI275pGhXl0PP_UkfK_CAz5Z2hcWsW9Ny2fdU4C1f5aSchFVxA8vJjlTPRhqZzDQMRB7AklwJ0xXtX0ZSKH1h24ghoKAdGY23FhxC4nS2pDvxzIvxb-8THU0XlEQJ-ZB7SnXTAvc_LhOckhMdLBnbtndpb-SB7a8q2SRD_W00
56
82
 
57
- this._duplex = new DuplexStreamFactory<Uint8Array, Uint8Array>({
83
+ this._duplex = new DuplexStreamFactory<
84
+ Uint8Array,
85
+ Consumable<Uint8Array>
86
+ >({
58
87
  close: async () => {
59
88
  this._closed = true;
60
89
 
@@ -69,22 +98,27 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
69
98
  },
70
99
  dispose: () => {
71
100
  // Error out the pending writes
72
- this._writePromise?.reject(new Error('Socket closed'));
101
+ this._writePromise?.reject(new Error("Socket closed"));
73
102
  },
74
103
  });
75
104
 
76
105
  this._readable = this._duplex.wrapReadable(
77
- new PushReadableStream(controller => {
78
- this._readableController = controller;
79
- }, {
80
- highWaterMark: options.highWaterMark ?? 16 * 1024,
81
- size(chunk) { return chunk.byteLength; }
82
- })
106
+ new PushReadableStream(
107
+ (controller) => {
108
+ this._readableController = controller;
109
+ },
110
+ {
111
+ highWaterMark: options.highWaterMark ?? 16 * 1024,
112
+ size(chunk) {
113
+ return chunk.byteLength;
114
+ },
115
+ }
116
+ )
83
117
  );
84
118
 
85
119
  this.writable = pipeFrom(
86
120
  this._duplex.createWritable(
87
- new WritableStream({
121
+ new ConsumableWritableStream<Uint8Array>({
88
122
  write: async (chunk) => {
89
123
  // Wait for an ack packet
90
124
  this._writePromise = new PromiseResolver();
@@ -95,23 +129,23 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
95
129
  chunk
96
130
  );
97
131
  await this._writePromise.promise;
98
- }
99
- }),
132
+ },
133
+ })
100
134
  ),
101
- new ChunkStream(this.dispatcher.options.maxPayloadSize)
135
+ new DistributionStream(this.dispatcher.options.maxPayloadSize)
102
136
  );
103
137
 
104
138
  this._socket = new AdbSocket(this);
105
139
  }
106
140
 
107
- public async enqueue(packet: Uint8Array) {
141
+ public async enqueue(data: Uint8Array) {
108
142
  // Consumer may abort the `ReadableStream` to close the socket,
109
143
  // it's OK to throw away further packets in this case.
110
144
  if (this._readableController.abortSignal.aborted) {
111
145
  return;
112
146
  }
113
147
 
114
- await this._readableController.enqueue(packet);
148
+ await this._readableController.enqueue(data);
115
149
  }
116
150
 
117
151
  public ack() {
@@ -123,7 +157,7 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
123
157
  }
124
158
 
125
159
  public dispose() {
126
- this._duplex.dispose();
160
+ return this._duplex.dispose();
127
161
  }
128
162
  }
129
163
 
@@ -135,16 +169,32 @@ export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<
135
169
  * `socket.writable.abort()`, `socket.writable.getWriter().abort()`,
136
170
  * `socket.writable.close()` or `socket.writable.getWriter().close()`.
137
171
  */
138
- export class AdbSocket implements AdbSocketInfo, ReadableWritablePair<Uint8Array, Uint8Array>{
172
+ export class AdbSocket
173
+ implements
174
+ AdbSocketInfo,
175
+ ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>
176
+ {
139
177
  private _controller: AdbSocketController;
140
178
 
141
- public get localId(): number { return this._controller.localId; }
142
- public get remoteId(): number { return this._controller.remoteId; }
143
- public get localCreated(): boolean { return this._controller.localCreated; }
144
- public get serviceString(): string { return this._controller.serviceString; }
179
+ public get localId(): number {
180
+ return this._controller.localId;
181
+ }
182
+ public get remoteId(): number {
183
+ return this._controller.remoteId;
184
+ }
185
+ public get localCreated(): boolean {
186
+ return this._controller.localCreated;
187
+ }
188
+ public get serviceString(): string {
189
+ return this._controller.serviceString;
190
+ }
145
191
 
146
- public get readable(): ReadableStream<Uint8Array> { return this._controller.readable; }
147
- public get writable(): WritableStream<Uint8Array> { return this._controller.writable; }
192
+ public get readable(): ReadableStream<Uint8Array> {
193
+ return this._controller.readable;
194
+ }
195
+ public get writable(): WritableStream<Consumable<Uint8Array>> {
196
+ return this._controller.writable;
197
+ }
148
198
 
149
199
  public constructor(controller: AdbSocketController) {
150
200
  this._controller = controller;
@@ -1,41 +1,40 @@
1
- import { PromiseResolver } from '@yume-chan/async';
2
- import type { Disposable } from '@yume-chan/event';
1
+ import { PromiseResolver } from "@yume-chan/async";
2
+ import type { Disposable } from "@yume-chan/event";
3
3
 
4
4
  export class AutoResetEvent implements Disposable {
5
- private readonly list: PromiseResolver<void>[] = [];
6
-
7
- private blocking: boolean;
5
+ private _set: boolean;
6
+ private readonly _queue: PromiseResolver<void>[] = [];
8
7
 
9
8
  public constructor(initialSet = false) {
10
- this.blocking = initialSet;
9
+ this._set = initialSet;
11
10
  }
12
11
 
13
12
  public wait(): Promise<void> {
14
- if (!this.blocking) {
15
- this.blocking = true;
13
+ if (!this._set) {
14
+ this._set = true;
16
15
 
17
- if (this.list.length === 0) {
16
+ if (this._queue.length === 0) {
18
17
  return Promise.resolve();
19
18
  }
20
19
  }
21
20
 
22
21
  const resolver = new PromiseResolver<void>();
23
- this.list.push(resolver);
22
+ this._queue.push(resolver);
24
23
  return resolver.promise;
25
24
  }
26
25
 
27
- public notify() {
28
- if (this.list.length !== 0) {
29
- this.list.pop()!.resolve();
26
+ public notifyOne() {
27
+ if (this._queue.length !== 0) {
28
+ this._queue.pop()!.resolve();
30
29
  } else {
31
- this.blocking = false;
30
+ this._set = false;
32
31
  }
33
32
  }
34
33
 
35
34
  public dispose() {
36
- for (const item of this.list) {
37
- item.reject(new Error('The AutoResetEvent has been disposed'));
35
+ for (const item of this._queue) {
36
+ item.reject(new Error("The AutoResetEvent has been disposed"));
38
37
  }
39
- this.list.length = 0;
38
+ this._queue.length = 0;
40
39
  }
41
40
  }