@yume-chan/adb 3.0.0-beta.0 → 3.0.0-beta.2

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 (134) hide show
  1. package/esm/adb.d.ts +7 -2
  2. package/esm/adb.d.ts.map +1 -1
  3. package/esm/adb.js +2 -2
  4. package/esm/adb.js.map +1 -1
  5. package/esm/banner.spec.d.ts +2 -0
  6. package/esm/banner.spec.d.ts.map +1 -0
  7. package/esm/daemon/auth/packet-processor.spec.d.ts +2 -0
  8. package/esm/daemon/auth/packet-processor.spec.d.ts.map +1 -0
  9. package/esm/daemon/auth/public-key.spec.d.ts +2 -0
  10. package/esm/daemon/auth/public-key.spec.d.ts.map +1 -0
  11. package/esm/daemon/crypto.spec.d.ts +2 -0
  12. package/esm/daemon/crypto.spec.d.ts.map +1 -0
  13. package/esm/server/client.d.ts +4 -3
  14. package/esm/server/client.d.ts.map +1 -1
  15. package/esm/server/client.js +13 -12
  16. package/esm/server/client.js.map +1 -1
  17. package/esm/server/client.spec.d.ts +2 -0
  18. package/esm/server/client.spec.d.ts.map +1 -0
  19. package/esm/server/transport.d.ts +1 -1
  20. package/esm/server/transport.d.ts.map +1 -1
  21. package/esm/server/transport.js +2 -2
  22. package/esm/server/transport.js.map +1 -1
  23. package/esm/service/reverse/response.spec.d.ts +2 -0
  24. package/esm/service/reverse/response.spec.d.ts.map +1 -0
  25. package/esm/service/subprocess/none/process.spec.d.ts +2 -0
  26. package/esm/service/subprocess/none/process.spec.d.ts.map +1 -0
  27. package/esm/service/subprocess/none/spawner.d.ts.map +1 -1
  28. package/esm/service/subprocess/none/spawner.js +10 -5
  29. package/esm/service/subprocess/none/spawner.js.map +1 -1
  30. package/esm/service/subprocess/none/spawner.spec.d.ts +2 -0
  31. package/esm/service/subprocess/none/spawner.spec.d.ts.map +1 -0
  32. package/esm/service/subprocess/shell/process.d.ts.map +1 -1
  33. package/esm/service/subprocess/shell/process.js +7 -9
  34. package/esm/service/subprocess/shell/process.js.map +1 -1
  35. package/esm/service/subprocess/shell/process.spec.d.ts +2 -0
  36. package/esm/service/subprocess/shell/process.spec.d.ts.map +1 -0
  37. package/esm/service/subprocess/shell/shared.spec.d.ts +2 -0
  38. package/esm/service/subprocess/shell/shared.spec.d.ts.map +1 -0
  39. package/esm/service/subprocess/shell/spawner.d.ts.map +1 -1
  40. package/esm/service/subprocess/shell/spawner.js +16 -11
  41. package/esm/service/subprocess/shell/spawner.js.map +1 -1
  42. package/esm/service/subprocess/shell/spawner.spec.d.ts +2 -0
  43. package/esm/service/subprocess/shell/spawner.spec.d.ts.map +1 -0
  44. package/esm/service/subprocess/utils.spec.d.ts +2 -0
  45. package/esm/service/subprocess/utils.spec.d.ts.map +1 -0
  46. package/esm/service/sync/compression/adapters.d.ts +16 -0
  47. package/esm/service/sync/compression/adapters.d.ts.map +1 -0
  48. package/esm/service/sync/compression/adapters.js +84 -0
  49. package/esm/service/sync/compression/adapters.js.map +1 -0
  50. package/esm/service/sync/compression/format-ns.d.ts.map +1 -1
  51. package/esm/service/sync/compression/format-ns.js +1 -0
  52. package/esm/service/sync/compression/format-ns.js.map +1 -1
  53. package/esm/service/sync/compression/format.d.ts +1 -0
  54. package/esm/service/sync/compression/format.d.ts.map +1 -1
  55. package/esm/service/sync/compression/format.js +1 -0
  56. package/esm/service/sync/compression/format.js.map +1 -1
  57. package/esm/service/sync/compression/index.d.ts +1 -1
  58. package/esm/service/sync/compression/index.d.ts.map +1 -1
  59. package/esm/service/sync/compression/index.js +1 -1
  60. package/esm/service/sync/compression/index.js.map +1 -1
  61. package/esm/service/sync/compression/mode.d.ts +6 -0
  62. package/esm/service/sync/compression/mode.d.ts.map +1 -0
  63. package/esm/service/sync/compression/mode.js +5 -0
  64. package/esm/service/sync/compression/mode.js.map +1 -0
  65. package/esm/service/sync/compression/native.d.ts +8 -0
  66. package/esm/service/sync/compression/native.d.ts.map +1 -0
  67. package/esm/service/sync/compression/native.js +53 -0
  68. package/esm/service/sync/compression/native.js.map +1 -0
  69. package/esm/service/sync/id/request.d.ts +1 -0
  70. package/esm/service/sync/id/request.d.ts.map +1 -1
  71. package/esm/service/sync/id/request.js +1 -0
  72. package/esm/service/sync/id/request.js.map +1 -1
  73. package/esm/service/sync/request/flag.d.ts +9 -0
  74. package/esm/service/sync/request/flag.d.ts.map +1 -0
  75. package/esm/service/sync/request/flag.js +8 -0
  76. package/esm/service/sync/request/flag.js.map +1 -0
  77. package/esm/service/sync/request/pull.d.ts +25 -2
  78. package/esm/service/sync/request/pull.d.ts.map +1 -1
  79. package/esm/service/sync/request/pull.js +76 -16
  80. package/esm/service/sync/request/pull.js.map +1 -1
  81. package/esm/service/sync/request/push.d.ts +36 -14
  82. package/esm/service/sync/request/push.d.ts.map +1 -1
  83. package/esm/service/sync/request/push.js +176 -60
  84. package/esm/service/sync/request/push.js.map +1 -1
  85. package/esm/service/sync/service.d.ts +32 -16
  86. package/esm/service/sync/service.d.ts.map +1 -1
  87. package/esm/service/sync/service.js +58 -13
  88. package/esm/service/sync/service.js.map +1 -1
  89. package/esm/service/sync/socket-pool.d.ts +1 -0
  90. package/esm/service/sync/socket-pool.d.ts.map +1 -1
  91. package/esm/service/sync/socket-pool.js +45 -9
  92. package/esm/service/sync/socket-pool.js.map +1 -1
  93. package/esm/service/sync/socket-pool.spec.d.ts +2 -0
  94. package/esm/service/sync/socket-pool.spec.d.ts.map +1 -0
  95. package/esm/service/sync/socket.d.ts +4 -0
  96. package/esm/service/sync/socket.d.ts.map +1 -1
  97. package/esm/service/sync/socket.js +16 -0
  98. package/esm/service/sync/socket.js.map +1 -1
  99. package/esm/service/sync/socket.spec.d.ts +2 -0
  100. package/esm/service/sync/socket.spec.d.ts.map +1 -0
  101. package/esm/utils/base64.spec.d.ts +2 -0
  102. package/esm/utils/base64.spec.d.ts.map +1 -0
  103. package/esm/utils/md5.spec.d.ts +2 -0
  104. package/esm/utils/md5.spec.d.ts.map +1 -0
  105. package/esm/utils/ref.d.ts +3 -5
  106. package/esm/utils/ref.d.ts.map +1 -1
  107. package/esm/utils/ref.js +12 -6
  108. package/esm/utils/ref.js.map +1 -1
  109. package/package.json +7 -7
  110. package/src/adb.ts +15 -3
  111. package/src/server/client.ts +18 -11
  112. package/src/server/transport.ts +5 -1
  113. package/src/service/subprocess/none/spawner.ts +9 -5
  114. package/src/service/subprocess/shell/process.ts +7 -10
  115. package/src/service/subprocess/shell/spawner.ts +15 -11
  116. package/src/service/sync/compression/adapters.ts +137 -0
  117. package/src/service/sync/compression/format-ns.ts +2 -0
  118. package/src/service/sync/compression/format.ts +5 -0
  119. package/src/service/sync/compression/index.ts +1 -1
  120. package/src/service/sync/compression/mode.ts +6 -0
  121. package/src/service/sync/compression/native.ts +73 -0
  122. package/src/service/sync/id/request.ts +1 -0
  123. package/src/service/sync/request/flag.ts +9 -0
  124. package/src/service/sync/request/pull.ts +135 -27
  125. package/src/service/sync/request/push.ts +241 -91
  126. package/src/service/sync/service.ts +87 -27
  127. package/src/service/sync/socket-pool.ts +50 -9
  128. package/src/service/sync/socket.ts +23 -1
  129. package/src/utils/ref.ts +17 -7
  130. package/esm/service/sync/compression/compression.d.ts +0 -17
  131. package/esm/service/sync/compression/compression.d.ts.map +0 -1
  132. package/esm/service/sync/compression/compression.js +0 -92
  133. package/esm/service/sync/compression/compression.js.map +0 -1
  134. package/src/service/sync/compression/compression.ts +0 -126
@@ -1,8 +1,5 @@
1
- import type {
2
- AbortSignal,
3
- MaybeConsumable,
4
- ReadableStream,
5
- } from "@yume-chan/stream-extra";
1
+ import type { AbortSignal, ReadableStream } from "@yume-chan/stream-extra";
2
+ import { MaybeConsumable } from "@yume-chan/stream-extra";
6
3
 
7
4
  import type { Adb } from "../../adb.js";
8
5
  import { AdbFeature } from "../../features.js";
@@ -53,20 +50,20 @@ export function dirname(path: string): string {
53
50
  }
54
51
 
55
52
  export interface WriteOptions {
56
- filename: string;
57
- file: ReadableStream<MaybeConsumable<Uint8Array>>;
53
+ path: string;
58
54
  type?: LinuxFileType | undefined;
59
55
  permission?: number | undefined;
60
56
  mtime?: number | undefined;
61
57
  /**
62
58
  * The format to compress the file stream for sending.
63
59
  *
64
- * If the device doesn't support compressed sending, it will be ignored.
60
+ * If the device doesn't support compressed sending, the value will be ignored.
65
61
  *
66
- * If the device or current runtime doesn't support the specified format,
62
+ * Otherwise, if the device or current runtime doesn't support the specified format,
67
63
  * an Error will be thrown.
68
- * {@link Compression.canUseFormat} can be used to check if
69
- * the device and current runtime both supports the format.
64
+ *
65
+ * If `undefined` is specified, automatically choose the best format
66
+ * supported by both device and current runtime.
70
67
  */
71
68
  compression?: Compression.Format | undefined;
72
69
  dryRun?: boolean | undefined;
@@ -203,36 +200,73 @@ export class Service {
203
200
  }
204
201
 
205
202
  /**
206
- * Reads the content of a file on device.
207
- *
208
- * @param filename The full path of the file on device to read.
209
- * @returns A `ReadableStream` that contains the file content.
203
+ * Creates a readable stream to read the content of a file on device.
204
+ * @param path The full path of the file on device to read.
205
+ * @param compression The compression format to use for reading the file. If the device doesn't support compressed reading, the value will be ignored.
206
+ * @returns A {@link Receive.ReceiveSession} object that contains a readable stream to read the file content.
210
207
  */
211
- read(filename: string): ReadableStream<Uint8Array> {
212
- return Receive.stream(this.#socketPool, filename);
208
+ createReadable(
209
+ path: string,
210
+ compression?: Compression.Format,
211
+ ): Receive.ReceiveSession {
212
+ if (this.#supportsSendReceive2) {
213
+ if (compression === undefined) {
214
+ compression = Compression.chooseFormat(
215
+ this._adb,
216
+ Compression.Mode.Decompress,
217
+ );
218
+ } else if (
219
+ !Compression.canUseFormat(
220
+ this._adb,
221
+ compression,
222
+ Compression.Mode.Decompress,
223
+ )
224
+ ) {
225
+ throw new Error(
226
+ `Compression type ${Compression.FormatNameMap[compression]} is not supported`,
227
+ );
228
+ }
229
+ return Receive.receiveV2(this.#socketPool, path, compression);
230
+ } else {
231
+ return Receive.receiveV1(this.#socketPool, path);
232
+ }
213
233
  }
214
234
 
215
235
  /**
216
- * Writes a file on device. If the file name already exists, it will be overwritten.
236
+ * Creates a readable stream to read the content of a file on device.
217
237
  *
218
- * @param options The content and options of the file to write.
238
+ * @param path The full path of the file on device to read.
239
+ * @returns A readable stream to read the file content.
219
240
  */
220
- async write(options: WriteOptions): Promise<void> {
241
+ read(path: string): ReadableStream<Uint8Array> {
242
+ const session = this.createReadable(path);
243
+ return session.readable;
244
+ }
245
+
246
+ /**
247
+ * Creates a writable stream to write a file
248
+ * @param options The options for writing the file, including the path, type, permission, mtime, and compression format.
249
+ * @returns A {@link SendSession} object that contains a writable stream to write the file content.
250
+ */
251
+ async createWritable(options: WriteOptions): Promise<Send.SendSession> {
221
252
  if (this.needPushMkdirWorkaround) {
222
253
  // It may fail if `filename` already exists.
223
254
  // Ignore the result.
224
255
  // TODO: sync: test push mkdir workaround (need an Android 8 device)
225
256
  await this._adb.subprocess.noneProtocol
226
- .spawn(["mkdir", "-p", escapeArg(dirname(options.filename))])
257
+ .spawn(["mkdir", "-p", escapeArg(dirname(options.path))])
227
258
  .wait();
228
259
  }
229
260
 
230
261
  if (this.supportsSendReceive2) {
231
262
  if (options.compression === undefined) {
232
- options.compression = Compression.chooseFormat(
233
- this._adb,
234
- Compression.Mode.Compress,
235
- );
263
+ options = {
264
+ ...options,
265
+ compression: Compression.chooseFormat(
266
+ this._adb,
267
+ Compression.Mode.Compress,
268
+ ),
269
+ };
236
270
  } else if (
237
271
  !Compression.canUseFormat(
238
272
  this._adb,
@@ -241,15 +275,41 @@ export class Service {
241
275
  )
242
276
  ) {
243
277
  throw new Error(
244
- `Compression type ${options.compression} is not supported`,
278
+ `Compression type ${Compression.FormatNameMap[options.compression]} is not supported`,
245
279
  );
246
280
  }
281
+ } else {
282
+ options = {
283
+ ...options,
284
+ compression: undefined,
285
+ };
247
286
  }
248
287
 
249
- await Send.send({
288
+ return await Send.send({
250
289
  version: this.supportsSendReceive2 ? 2 : 1,
251
290
  pool: this.#socketPool,
252
291
  ...options,
253
292
  });
254
293
  }
294
+
295
+ /**
296
+ * Writes a file to the device using a readable stream.
297
+ * @param options The options for writing the file, including the path, type, permission, mtime, compression format, and a readable stream to read the file content.
298
+ * @returns An object that contains the number of bytes written, the compression format used (if any), and the size of the compressed data written (if any).
299
+ */
300
+ async write(
301
+ options: WriteOptions & {
302
+ readable: ReadableStream<MaybeConsumable<Uint8Array>>;
303
+ },
304
+ ): Promise<Omit<Send.SendSession, "writable">> {
305
+ const session = await this.createWritable(options);
306
+ await options.readable.pipeTo(
307
+ new MaybeConsumable.WrapWritableStream(session.writable),
308
+ );
309
+ return {
310
+ bytesWritten: session.bytesWritten,
311
+ compression: session.compression,
312
+ bytesCompressed: session.bytesCompressed,
313
+ };
314
+ }
255
315
  }
@@ -1,4 +1,5 @@
1
1
  import type { Adb } from "../../adb.js";
2
+ import { Ref } from "../../utils/ref.js";
2
3
 
3
4
  import { Error as AdbSyncError, Socket } from "./socket.js";
4
5
 
@@ -8,6 +9,7 @@ export class SocketPool {
8
9
  readonly #idleTimeout: number;
9
10
  readonly #availableSockets: Socket[] = [];
10
11
  readonly #inUseSockets = new Set<Socket>();
12
+ #ref = new Ref({ unref: true });
11
13
  #closed = false;
12
14
 
13
15
  constructor(adb: Adb, maxSize = 4, idleTimeout = 60000) {
@@ -26,18 +28,32 @@ export class SocketPool {
26
28
  // Clear the idle timeout
27
29
  socket.clearIdleTimer();
28
30
  this.#inUseSockets.add(socket);
31
+ this.#ref.ref();
29
32
  return socket;
30
33
  }
31
34
 
32
- // Create a new socket
33
- const adbSocket = await this.#adb.createSocket("sync:");
34
- if (this.#closed) {
35
- await adbSocket.close();
36
- throw new Error("SocketPool is closed");
35
+ try {
36
+ // Add ref early to keep the process alive while initializing the new socket
37
+ this.#ref.ref();
38
+
39
+ // Create a new socket
40
+ const adbSocket = await this.#adb.createSocket("sync:", {
41
+ unref: true,
42
+ });
43
+
44
+ if (this.#closed) {
45
+ await adbSocket.close();
46
+ throw new Error("SocketPool is closed");
47
+ }
48
+
49
+ const socket = new Socket(adbSocket, this.#adb.maxPayloadSize);
50
+ this.#inUseSockets.add(socket);
51
+
52
+ return socket;
53
+ } catch (e) {
54
+ this.#ref.unref();
55
+ throw e;
37
56
  }
38
- const socket = new Socket(adbSocket, this.#adb.maxPayloadSize);
39
- this.#inUseSockets.add(socket);
40
- return socket;
41
57
  }
42
58
 
43
59
  async withSocket<T>(fn: (socket: Socket) => Promise<T>): Promise<T> {
@@ -52,8 +68,32 @@ export class SocketPool {
52
68
  }
53
69
  }
54
70
 
71
+ async *withSocketGenerator<T>(
72
+ fn: (socket: Socket) => AsyncGenerator<T, void, void>,
73
+ ): AsyncGenerator<T, void, void> {
74
+ const socket = await this.acquire();
75
+ let discard = true;
76
+ try {
77
+ for await (const value of fn(socket)) {
78
+ yield value;
79
+ }
80
+ discard = false;
81
+ } catch (e) {
82
+ discard = !(e instanceof AdbSyncError);
83
+ throw e;
84
+ } finally {
85
+ // When the generator is retuned early, `discard` will have the default value of `true`,
86
+ // the socket needs to be closed, so the server will stop sending data.
87
+ await this.release(socket, discard);
88
+ }
89
+ }
90
+
55
91
  async release(socket: Socket, discard = false): Promise<void> {
56
- this.#inUseSockets.delete(socket);
92
+ if (!this.#inUseSockets.delete(socket)) {
93
+ return;
94
+ }
95
+
96
+ this.#ref.unref();
57
97
 
58
98
  // If discarding or we already have enough sockets in the pool, close this socket
59
99
  if (discard || this.#availableSockets.length >= this.#maxSize) {
@@ -91,6 +131,7 @@ export class SocketPool {
91
131
  (socket) => socket.close(),
92
132
  );
93
133
  this.#inUseSockets.clear();
134
+ this.#ref.dispose();
94
135
 
95
136
  await Promise.all([...closePromises, ...inUseClosePromises]);
96
137
  }
@@ -21,7 +21,15 @@ import { ResponseId } from "./id/index.js";
21
21
 
22
22
  const NumberRequest = struct({ id: u32, arg: u32 }, { littleEndian: true });
23
23
 
24
- class AdbSyncError extends Error {}
24
+ const AdbSyncErrorBrand = Symbol.for("AdbSyncError.brand");
25
+
26
+ class AdbSyncError extends Error {
27
+ [AdbSyncErrorBrand] = true;
28
+
29
+ static override [Symbol.hasInstance](value: unknown) {
30
+ return !!(value as AdbSyncError | undefined)?.[AdbSyncErrorBrand];
31
+ }
32
+ }
25
33
  export { AdbSyncError as Error };
26
34
 
27
35
  const FailResponse = struct(
@@ -38,10 +46,13 @@ function i32ToHex(i: number) {
38
46
  return "0x" + i.toString(16).padStart(8, "0");
39
47
  }
40
48
 
49
+ let NextId = 0;
50
+
41
51
  export class Socket implements AsyncExactReadable {
42
52
  static readonly NumberRequest = NumberRequest;
43
53
  static readonly FailResponse = FailResponse;
44
54
 
55
+ #id: number;
45
56
  readonly #socket: Adb.Socket;
46
57
  readonly #writer: WritableStreamDefaultWriter<MaybeConsumable<Uint8Array>>;
47
58
  readonly #readable: BufferedReadableStream;
@@ -49,6 +60,10 @@ export class Socket implements AsyncExactReadable {
49
60
  readonly #combiner: BufferCombiner;
50
61
  #idleTimeoutId: ReturnType<typeof setTimeout> | null = null;
51
62
 
63
+ get id() {
64
+ return this.#id;
65
+ }
66
+
52
67
  get position() {
53
68
  return this.#readable.position;
54
69
  }
@@ -58,6 +73,9 @@ export class Socket implements AsyncExactReadable {
58
73
  }
59
74
 
60
75
  constructor(socket: Adb.Socket, bufferSize: number) {
76
+ this.#id = NextId;
77
+ NextId += 1;
78
+
61
79
  this.#socket = socket;
62
80
  this.#writer = socket.writable.getWriter();
63
81
  this.#readable = new BufferedReadableStream(socket.readable);
@@ -73,6 +91,10 @@ export class Socket implements AsyncExactReadable {
73
91
  startIdleTimer(timeout: number, callback: () => void) {
74
92
  this.clearIdleTimer();
75
93
  this.#idleTimeoutId = setTimeout(callback, timeout);
94
+ if (typeof this.#idleTimeoutId === "object") {
95
+ // Node.js: unref the timer so that it won't keep the process alive
96
+ (this.#idleTimeoutId as { unref?: () => void }).unref?.();
97
+ }
76
98
  }
77
99
 
78
100
  /**
package/src/utils/ref.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { Disposable } from "@yume-chan/event";
2
+
1
3
  interface GlobalExtension {
2
4
  setInterval: (callback: () => void, delay: number) => number;
3
5
  clearInterval: (id: number) => void;
@@ -9,14 +11,12 @@ const { setInterval, clearInterval } = globalThis as unknown as GlobalExtension;
9
11
  * An object to keep current Node.js process alive even when no code is running.
10
12
  *
11
13
  * Does nothing in Web environments.
12
- *
13
- * Note that it does't have reference counting. Calling `unref` will
14
- * remove the ref no matter how many times `ref` has been previously called, and vice versa.
15
- * This is the same as how Node.js works.
16
14
  */
17
- export class Ref {
15
+ export class Ref implements Disposable {
18
16
  #intervalId: number | undefined;
19
17
 
18
+ #count = 0;
19
+
20
20
  constructor(options?: { unref?: boolean | undefined }) {
21
21
  if (!options?.unref) {
22
22
  this.ref();
@@ -24,11 +24,21 @@ export class Ref {
24
24
  }
25
25
 
26
26
  ref() {
27
- // `setInterval` can keep current Node.js alive, the delay value doesn't matter
28
- this.#intervalId = setInterval(() => {}, 60 * 1000);
27
+ if (this.#count === 0) {
28
+ // `setInterval` can keep current Node.js alive, the delay value doesn't matter
29
+ this.#intervalId = setInterval(() => {}, 60 * 1000);
30
+ }
31
+ this.#count += 1;
29
32
  }
30
33
 
31
34
  unref() {
35
+ this.#count -= 1;
36
+ if (this.#count === 0) {
37
+ this.dispose();
38
+ }
39
+ }
40
+
41
+ dispose(): void {
32
42
  if (this.#intervalId) {
33
43
  clearInterval(this.#intervalId);
34
44
  this.#intervalId = undefined;
@@ -1,17 +0,0 @@
1
- import { CompressionStream } from "@yume-chan/stream-extra";
2
- import type { Adb } from "../../../adb.js";
3
- import { Format } from "./format.js";
4
- export { Format };
5
- export declare const Mode: {
6
- readonly Compress: 0;
7
- readonly Decompress: 1;
8
- };
9
- export type Mode = (typeof Mode)[keyof typeof Mode];
10
- export declare function hasRuntimeSupport(format: Format, mode: Mode): boolean;
11
- export declare function canUseBrotli(adb: Adb, mode: Mode): boolean;
12
- export declare function canUseLz4(adb: Adb, mode: Mode): boolean;
13
- export declare function canUseZstd(adb: Adb, mode: Mode): boolean;
14
- export declare function canUseFormat(adb: Adb, format: Format, mode: Mode): boolean;
15
- export declare function chooseFormat(adb: Adb, mode: Mode): 0 | 3 | 4 | 2;
16
- export declare function createCompressionStream(format: Format): CompressionStream;
17
- //# sourceMappingURL=compression.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../../../../src/service/sync/compression/compression.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,iBAAiB,EAGpB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAI3C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,MAAM,EAAE,CAAC;AAElB,eAAO,MAAM,IAAI;;;CAGP,CAAC;AAEX,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,OAAO,IAAI,CAAC,CAAC;AAepD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,WA4B3D;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,WAKhD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,WAK7C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,WAK9C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,WAahE;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,iBAiBhD;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAMzE"}
@@ -1,92 +0,0 @@
1
- import { CompressionStream, DecompressionStream, TransformStream, } from "@yume-chan/stream-extra";
2
- import { AdbFeature } from "../../../features.js";
3
- import { NOOP } from "../../../utils/no-op.js";
4
- import { Format } from "./format.js";
5
- export { Format };
6
- export const Mode = {
7
- Compress: 0,
8
- Decompress: 1,
9
- };
10
- const FormatMap = {
11
- [Format.None]: "",
12
- // https://github.com/whatwg/compression/pull/80
13
- [Format.Zstd]: "zstd",
14
- // placeholder
15
- [Format.Lz4]: "lz4",
16
- // https://github.com/whatwg/compression/pull/80
17
- [Format.Brotli]: "brotli",
18
- };
19
- const CompressionFormatCache = new Map();
20
- const DecompressionFormatCache = new Map();
21
- export function hasRuntimeSupport(format, mode) {
22
- if (format === Format.None) {
23
- return true;
24
- }
25
- const Cache = mode === Mode.Compress
26
- ? CompressionFormatCache
27
- : DecompressionFormatCache;
28
- if (Cache.has(format)) {
29
- return Cache.get(format);
30
- }
31
- const Stream = mode === Mode.Compress ? CompressionStream : DecompressionStream;
32
- if (!Stream) {
33
- return false;
34
- }
35
- try {
36
- const stream = new Stream(FormatMap[format]);
37
- void stream.writable.abort().catch(NOOP);
38
- Cache.set(format, true);
39
- return true;
40
- }
41
- catch {
42
- Cache.set(format, false);
43
- return false;
44
- }
45
- }
46
- export function canUseBrotli(adb, mode) {
47
- return (adb.canUseFeature(AdbFeature.SendReceive2Brotli) &&
48
- hasRuntimeSupport(Format.Brotli, mode));
49
- }
50
- export function canUseLz4(adb, mode) {
51
- return (adb.canUseFeature(AdbFeature.SendReceive2Lz4) &&
52
- hasRuntimeSupport(Format.Lz4, mode));
53
- }
54
- export function canUseZstd(adb, mode) {
55
- return (adb.canUseFeature(AdbFeature.SendReceive2Zstd) &&
56
- hasRuntimeSupport(Format.Zstd, mode));
57
- }
58
- export function canUseFormat(adb, format, mode) {
59
- switch (format) {
60
- case Format.None:
61
- return true;
62
- case Format.Brotli:
63
- return canUseBrotli(adb, mode);
64
- case Format.Lz4:
65
- return canUseLz4(adb, mode);
66
- case Format.Zstd:
67
- return canUseZstd(adb, mode);
68
- default:
69
- return false;
70
- }
71
- }
72
- export function chooseFormat(adb, mode) {
73
- // The order follows
74
- // https://android.googlesource.com/platform/packages/modules/adb/+/3da39565cad412a743a58b94b875a43ed3c640d3/client/file_sync_client.cpp#277
75
- if (canUseZstd(adb, mode)) {
76
- return Format.Zstd;
77
- }
78
- if (canUseLz4(adb, mode)) {
79
- return Format.Lz4;
80
- }
81
- if (canUseBrotli(adb, mode)) {
82
- return Format.Brotli;
83
- }
84
- return Format.None;
85
- }
86
- export function createCompressionStream(format) {
87
- if (format === Format.None) {
88
- return new TransformStream();
89
- }
90
- return new CompressionStream(FormatMap[format]);
91
- }
92
- //# sourceMappingURL=compression.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"compression.js","sourceRoot":"","sources":["../../../../src/service/sync/compression/compression.ts"],"names":[],"mappings":"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"}
@@ -1,126 +0,0 @@
1
- import {
2
- CompressionStream,
3
- DecompressionStream,
4
- TransformStream,
5
- } from "@yume-chan/stream-extra";
6
-
7
- import type { Adb } from "../../../adb.js";
8
- import { AdbFeature } from "../../../features.js";
9
- import { NOOP } from "../../../utils/no-op.js";
10
-
11
- import { Format } from "./format.js";
12
-
13
- export { Format };
14
-
15
- export const Mode = {
16
- Compress: 0,
17
- Decompress: 1,
18
- } as const;
19
-
20
- export type Mode = (typeof Mode)[keyof typeof Mode];
21
-
22
- const FormatMap: Record<Format, string> = {
23
- [Format.None]: "",
24
- // https://github.com/whatwg/compression/pull/80
25
- [Format.Zstd]: "zstd",
26
- // placeholder
27
- [Format.Lz4]: "lz4",
28
- // https://github.com/whatwg/compression/pull/80
29
- [Format.Brotli]: "brotli",
30
- };
31
-
32
- const CompressionFormatCache = new Map<Format, boolean>();
33
- const DecompressionFormatCache = new Map<Format, boolean>();
34
-
35
- export function hasRuntimeSupport(format: Format, mode: Mode) {
36
- if (format === Format.None) {
37
- return true;
38
- }
39
-
40
- const Cache =
41
- mode === Mode.Compress
42
- ? CompressionFormatCache
43
- : DecompressionFormatCache;
44
- if (Cache.has(format)) {
45
- return Cache.get(format)!;
46
- }
47
-
48
- const Stream =
49
- mode === Mode.Compress ? CompressionStream : DecompressionStream;
50
- if (!Stream) {
51
- return false;
52
- }
53
-
54
- try {
55
- const stream = new Stream(FormatMap[format]);
56
- void stream.writable.abort().catch(NOOP);
57
- Cache.set(format, true);
58
- return true;
59
- } catch {
60
- Cache.set(format, false);
61
- return false;
62
- }
63
- }
64
-
65
- export function canUseBrotli(adb: Adb, mode: Mode) {
66
- return (
67
- adb.canUseFeature(AdbFeature.SendReceive2Brotli) &&
68
- hasRuntimeSupport(Format.Brotli, mode)
69
- );
70
- }
71
-
72
- export function canUseLz4(adb: Adb, mode: Mode) {
73
- return (
74
- adb.canUseFeature(AdbFeature.SendReceive2Lz4) &&
75
- hasRuntimeSupport(Format.Lz4, mode)
76
- );
77
- }
78
-
79
- export function canUseZstd(adb: Adb, mode: Mode) {
80
- return (
81
- adb.canUseFeature(AdbFeature.SendReceive2Zstd) &&
82
- hasRuntimeSupport(Format.Zstd, mode)
83
- );
84
- }
85
-
86
- export function canUseFormat(adb: Adb, format: Format, mode: Mode) {
87
- switch (format) {
88
- case Format.None:
89
- return true;
90
- case Format.Brotli:
91
- return canUseBrotli(adb, mode);
92
- case Format.Lz4:
93
- return canUseLz4(adb, mode);
94
- case Format.Zstd:
95
- return canUseZstd(adb, mode);
96
- default:
97
- return false;
98
- }
99
- }
100
-
101
- export function chooseFormat(adb: Adb, mode: Mode) {
102
- // The order follows
103
- // https://android.googlesource.com/platform/packages/modules/adb/+/3da39565cad412a743a58b94b875a43ed3c640d3/client/file_sync_client.cpp#277
104
-
105
- if (canUseZstd(adb, mode)) {
106
- return Format.Zstd;
107
- }
108
-
109
- if (canUseLz4(adb, mode)) {
110
- return Format.Lz4;
111
- }
112
-
113
- if (canUseBrotli(adb, mode)) {
114
- return Format.Brotli;
115
- }
116
-
117
- return Format.None;
118
- }
119
-
120
- export function createCompressionStream(format: Format): CompressionStream {
121
- if (format === Format.None) {
122
- return new TransformStream();
123
- }
124
-
125
- return new CompressionStream(FormatMap[format]);
126
- }