@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.
- package/CHANGELOG.json +27 -0
- package/CHANGELOG.md +16 -1
- package/LICENSE +1 -1
- package/esm/adb.d.ts +63 -60
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +257 -229
- package/esm/adb.js.map +1 -1
- package/esm/auth.d.ts +51 -51
- package/esm/auth.d.ts.map +1 -1
- package/esm/auth.js +95 -96
- package/esm/auth.js.map +1 -1
- package/esm/backend.d.ts +8 -8
- package/esm/backend.d.ts.map +1 -1
- package/esm/backend.js +1 -1
- package/esm/commands/base.d.ts +6 -6
- package/esm/commands/base.js +8 -8
- package/esm/commands/framebuffer.d.ts +53 -53
- package/esm/commands/framebuffer.d.ts.map +1 -1
- package/esm/commands/framebuffer.js +46 -47
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/index.d.ts +7 -8
- package/esm/commands/index.d.ts.map +1 -1
- package/esm/commands/index.js +7 -8
- package/esm/commands/index.js.map +1 -1
- package/esm/commands/install.d.ts +9 -3
- package/esm/commands/install.d.ts.map +1 -1
- package/esm/commands/install.js +27 -21
- package/esm/commands/install.js.map +1 -1
- package/esm/commands/power.d.ts +22 -22
- package/esm/commands/power.d.ts.map +1 -1
- package/esm/commands/power.js +48 -44
- package/esm/commands/power.js.map +1 -1
- package/esm/commands/reverse.d.ts +41 -28
- package/esm/commands/reverse.d.ts.map +1 -1
- package/esm/commands/reverse.js +125 -98
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/command.d.ts +57 -51
- package/esm/commands/subprocess/command.d.ts.map +1 -1
- package/esm/commands/subprocess/command.js +86 -82
- package/esm/commands/subprocess/command.js.map +1 -1
- package/esm/commands/subprocess/index.d.ts +3 -3
- package/esm/commands/subprocess/index.js +3 -3
- package/esm/commands/subprocess/protocols/index.d.ts +3 -3
- package/esm/commands/subprocess/protocols/index.js +3 -3
- package/esm/commands/subprocess/protocols/none.d.ts +35 -35
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +65 -55
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/subprocess/protocols/shell.d.ts +39 -38
- package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/shell.js +166 -154
- package/esm/commands/subprocess/protocols/shell.js.map +1 -1
- package/esm/commands/subprocess/protocols/types.d.ts +49 -49
- package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/types.js +1 -1
- package/esm/commands/subprocess/utils.d.ts +1 -1
- package/esm/commands/subprocess/utils.js +18 -18
- package/esm/commands/sync/index.d.ts +8 -7
- package/esm/commands/sync/index.d.ts.map +1 -1
- package/esm/commands/sync/index.js +8 -7
- package/esm/commands/sync/index.js.map +1 -1
- package/esm/commands/sync/list.d.ts +42 -40
- package/esm/commands/sync/list.d.ts.map +1 -1
- package/esm/commands/sync/list.js +67 -35
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts +13 -11
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +35 -36
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/push.d.ts +46 -7
- package/esm/commands/sync/push.d.ts.map +1 -1
- package/esm/commands/sync/push.js +89 -23
- package/esm/commands/sync/push.js.map +1 -1
- package/esm/commands/sync/request.d.ts +26 -23
- package/esm/commands/sync/request.d.ts.map +1 -1
- package/esm/commands/sync/request.js +40 -42
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.d.ts +19 -19
- package/esm/commands/sync/response.d.ts.map +1 -1
- package/esm/commands/sync/response.js +54 -54
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/socket.d.ts +27 -0
- package/esm/commands/sync/socket.d.ts.map +1 -0
- package/esm/commands/sync/socket.js +66 -0
- package/esm/commands/sync/socket.js.map +1 -0
- package/esm/commands/sync/stat.d.ts +72 -72
- package/esm/commands/sync/stat.d.ts.map +1 -1
- package/esm/commands/sync/stat.js +116 -94
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts +72 -60
- package/esm/commands/sync/sync.d.ts.map +1 -1
- package/esm/commands/sync/sync.js +127 -148
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/commands/tcpip.d.ts +5 -5
- package/esm/commands/tcpip.js +18 -18
- package/esm/crypto.d.ts +36 -36
- package/esm/crypto.d.ts.map +1 -1
- package/esm/crypto.js +248 -238
- package/esm/crypto.js.map +1 -1
- package/esm/features.d.ts +10 -7
- package/esm/features.d.ts.map +1 -1
- package/esm/features.js +13 -10
- package/esm/features.js.map +1 -1
- package/esm/index.d.ts +9 -9
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +9 -9
- package/esm/index.js.map +1 -1
- package/esm/packet.d.ts +45 -46
- package/esm/packet.d.ts.map +1 -1
- package/esm/packet.js +43 -46
- package/esm/packet.js.map +1 -1
- package/esm/socket/dispatcher.d.ts +59 -59
- package/esm/socket/dispatcher.d.ts.map +1 -1
- package/esm/socket/dispatcher.js +223 -231
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/socket/index.d.ts +2 -2
- package/esm/socket/index.js +2 -2
- package/esm/socket/socket.d.ts +59 -59
- package/esm/socket/socket.d.ts.map +1 -1
- package/esm/socket/socket.js +118 -98
- package/esm/socket/socket.js.map +1 -1
- package/esm/utils/auto-reset-event.d.ts +9 -9
- package/esm/utils/auto-reset-event.d.ts.map +1 -1
- package/esm/utils/auto-reset-event.js +33 -33
- package/esm/utils/auto-reset-event.js.map +1 -1
- package/esm/utils/base64.d.ts +27 -27
- package/esm/utils/base64.d.ts.map +1 -1
- package/esm/utils/base64.js +246 -245
- package/esm/utils/base64.js.map +1 -1
- package/esm/utils/conditional-variable.d.ts +9 -0
- package/esm/utils/conditional-variable.d.ts.map +1 -0
- package/esm/utils/conditional-variable.js +34 -0
- package/esm/utils/conditional-variable.js.map +1 -0
- package/esm/utils/index.d.ts +4 -3
- package/esm/utils/index.d.ts.map +1 -1
- package/esm/utils/index.js +4 -3
- package/esm/utils/index.js.map +1 -1
- package/package.json +17 -13
- package/src/adb.ts +160 -101
- package/src/auth.ts +31 -22
- package/src/backend.ts +6 -4
- package/src/commands/base.ts +2 -2
- package/src/commands/framebuffer.ts +37 -41
- package/src/commands/index.ts +7 -8
- package/src/commands/power.ts +15 -11
- package/src/commands/reverse.ts +74 -30
- package/src/commands/subprocess/command.ts +34 -23
- package/src/commands/subprocess/index.ts +3 -3
- package/src/commands/subprocess/protocols/index.ts +3 -3
- package/src/commands/subprocess/protocols/none.ts +26 -11
- package/src/commands/subprocess/protocols/shell.ts +110 -56
- package/src/commands/subprocess/protocols/types.ts +10 -6
- package/src/commands/subprocess/utils.ts +1 -1
- package/src/commands/sync/index.ts +8 -7
- package/src/commands/sync/list.ts +74 -28
- package/src/commands/sync/pull.ts +49 -37
- package/src/commands/sync/push.ts +153 -32
- package/src/commands/sync/request.ts +37 -34
- package/src/commands/sync/response.ts +34 -27
- package/src/commands/sync/socket.ts +97 -0
- package/src/commands/sync/stat.ts +98 -70
- package/src/commands/sync/sync.ts +78 -97
- package/src/commands/tcpip.ts +5 -5
- package/src/crypto.ts +60 -32
- package/src/features.ts +9 -6
- package/src/index.ts +9 -10
- package/src/packet.ts +41 -46
- package/src/socket/dispatcher.ts +130 -108
- package/src/socket/index.ts +2 -2
- package/src/socket/socket.ts +84 -34
- package/src/utils/auto-reset-event.ts +16 -17
- package/src/utils/base64.ts +51 -41
- package/src/utils/conditional-variable.ts +45 -0
- package/src/utils/index.ts +4 -3
- package/tsconfig.build.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/src/commands/install.ts +0 -32
|
@@ -1,12 +1,28 @@
|
|
|
1
|
-
import { PromiseResolver } from
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
|
|
1
|
+
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
import type {
|
|
3
|
+
Consumable,
|
|
4
|
+
PushReadableStreamController,
|
|
5
|
+
ReadableStream,
|
|
6
|
+
WritableStreamDefaultWriter,
|
|
7
|
+
} from "@yume-chan/stream-extra";
|
|
8
|
+
import {
|
|
9
|
+
ConsumableTransformStream,
|
|
10
|
+
ConsumableWritableStream,
|
|
11
|
+
PushReadableStream,
|
|
12
|
+
StructDeserializeStream,
|
|
13
|
+
TransformStream,
|
|
14
|
+
WritableStream,
|
|
15
|
+
pipeFrom,
|
|
16
|
+
} from "@yume-chan/stream-extra";
|
|
17
|
+
import type { StructValueType } from "@yume-chan/struct";
|
|
18
|
+
import Struct, { placeholder } from "@yume-chan/struct";
|
|
19
|
+
|
|
20
|
+
import type { Adb } from "../../../adb.js";
|
|
21
|
+
import { AdbFeature } from "../../../features.js";
|
|
22
|
+
import type { AdbSocket } from "../../../socket/index.js";
|
|
23
|
+
import { encodeUtf8 } from "../../../utils/index.js";
|
|
24
|
+
|
|
25
|
+
import type { AdbSubprocessProtocol } from "./types.js";
|
|
10
26
|
|
|
11
27
|
export enum AdbShellProtocolId {
|
|
12
28
|
Stdin,
|
|
@@ -18,33 +34,38 @@ export enum AdbShellProtocolId {
|
|
|
18
34
|
}
|
|
19
35
|
|
|
20
36
|
// This packet format is used in both direction.
|
|
21
|
-
const AdbShellProtocolPacket =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
.uint8Array('data', { lengthField: 'length' });
|
|
37
|
+
const AdbShellProtocolPacket = new Struct({ littleEndian: true })
|
|
38
|
+
.uint8("id", placeholder<AdbShellProtocolId>())
|
|
39
|
+
.uint32("length")
|
|
40
|
+
.uint8Array("data", { lengthField: "length" });
|
|
26
41
|
|
|
27
|
-
type AdbShellProtocolPacketInit = typeof AdbShellProtocolPacket[
|
|
42
|
+
type AdbShellProtocolPacketInit = (typeof AdbShellProtocolPacket)["TInit"];
|
|
28
43
|
|
|
29
44
|
type AdbShellProtocolPacket = StructValueType<typeof AdbShellProtocolPacket>;
|
|
30
45
|
|
|
31
|
-
class StdinSerializeStream extends
|
|
46
|
+
class StdinSerializeStream extends ConsumableTransformStream<
|
|
47
|
+
Uint8Array,
|
|
48
|
+
AdbShellProtocolPacketInit
|
|
49
|
+
> {
|
|
32
50
|
constructor() {
|
|
33
51
|
super({
|
|
34
|
-
transform(chunk, controller) {
|
|
35
|
-
controller.enqueue({
|
|
52
|
+
async transform(chunk, controller) {
|
|
53
|
+
await controller.enqueue({
|
|
36
54
|
id: AdbShellProtocolId.Stdin,
|
|
37
55
|
data: chunk,
|
|
38
56
|
});
|
|
39
57
|
},
|
|
40
58
|
flush() {
|
|
41
59
|
// TODO: AdbShellSubprocessProtocol: support closing stdin
|
|
42
|
-
}
|
|
60
|
+
},
|
|
43
61
|
});
|
|
44
62
|
}
|
|
45
63
|
}
|
|
46
64
|
|
|
47
|
-
class StdoutDeserializeStream extends TransformStream<
|
|
65
|
+
class StdoutDeserializeStream extends TransformStream<
|
|
66
|
+
AdbShellProtocolPacket,
|
|
67
|
+
Uint8Array
|
|
68
|
+
> {
|
|
48
69
|
constructor(type: AdbShellProtocolId.Stdout | AdbShellProtocolId.Stderr) {
|
|
49
70
|
super({
|
|
50
71
|
transform(chunk, controller) {
|
|
@@ -56,15 +77,17 @@ class StdoutDeserializeStream extends TransformStream<AdbShellProtocolPacket, Ui
|
|
|
56
77
|
}
|
|
57
78
|
}
|
|
58
79
|
|
|
59
|
-
class MultiplexStream<T>{
|
|
80
|
+
class MultiplexStream<T> {
|
|
60
81
|
private _readable: PushReadableStream<T>;
|
|
61
82
|
private _readableController!: PushReadableStreamController<T>;
|
|
62
|
-
public get readable() {
|
|
83
|
+
public get readable() {
|
|
84
|
+
return this._readable;
|
|
85
|
+
}
|
|
63
86
|
|
|
64
87
|
private _activeCount = 0;
|
|
65
88
|
|
|
66
89
|
constructor() {
|
|
67
|
-
this._readable = new PushReadableStream(controller => {
|
|
90
|
+
this._readable = new PushReadableStream((controller) => {
|
|
68
91
|
this._readableController = controller;
|
|
69
92
|
});
|
|
70
93
|
}
|
|
@@ -77,13 +100,13 @@ class MultiplexStream<T>{
|
|
|
77
100
|
write: async (chunk) => {
|
|
78
101
|
await this._readableController.enqueue(chunk);
|
|
79
102
|
},
|
|
80
|
-
abort:
|
|
103
|
+
abort: () => {
|
|
81
104
|
this._activeCount -= 1;
|
|
82
105
|
if (this._activeCount === 0) {
|
|
83
106
|
this._readableController.close();
|
|
84
107
|
}
|
|
85
108
|
},
|
|
86
|
-
close:
|
|
109
|
+
close: () => {
|
|
87
110
|
this._activeCount -= 1;
|
|
88
111
|
if (this._activeCount === 0) {
|
|
89
112
|
this._readableController.close();
|
|
@@ -103,32 +126,46 @@ class MultiplexStream<T>{
|
|
|
103
126
|
*/
|
|
104
127
|
export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
|
|
105
128
|
public static isSupported(adb: Adb) {
|
|
106
|
-
return adb.
|
|
129
|
+
return adb.supportsFeature(AdbFeature.ShellV2);
|
|
107
130
|
}
|
|
108
131
|
|
|
109
132
|
public static async pty(adb: Adb, command: string) {
|
|
110
133
|
// TODO: AdbShellSubprocessProtocol: Support setting `XTERM` environment variable
|
|
111
|
-
return new AdbSubprocessShellProtocol(
|
|
134
|
+
return new AdbSubprocessShellProtocol(
|
|
135
|
+
await adb.createSocket(`shell,v2,pty:${command}`)
|
|
136
|
+
);
|
|
112
137
|
}
|
|
113
138
|
|
|
114
139
|
public static async raw(adb: Adb, command: string) {
|
|
115
|
-
return new AdbSubprocessShellProtocol(
|
|
140
|
+
return new AdbSubprocessShellProtocol(
|
|
141
|
+
await adb.createSocket(`shell,v2,raw:${command}`)
|
|
142
|
+
);
|
|
116
143
|
}
|
|
117
144
|
|
|
118
145
|
private readonly _socket: AdbSocket;
|
|
119
|
-
private _socketWriter: WritableStreamDefaultWriter<
|
|
146
|
+
private _socketWriter: WritableStreamDefaultWriter<
|
|
147
|
+
Consumable<AdbShellProtocolPacketInit>
|
|
148
|
+
>;
|
|
120
149
|
|
|
121
|
-
private _stdin: WritableStream<Uint8Array
|
|
122
|
-
public get stdin() {
|
|
150
|
+
private _stdin: WritableStream<Consumable<Uint8Array>>;
|
|
151
|
+
public get stdin() {
|
|
152
|
+
return this._stdin;
|
|
153
|
+
}
|
|
123
154
|
|
|
124
155
|
private _stdout: ReadableStream<Uint8Array>;
|
|
125
|
-
public get stdout() {
|
|
156
|
+
public get stdout() {
|
|
157
|
+
return this._stdout;
|
|
158
|
+
}
|
|
126
159
|
|
|
127
160
|
private _stderr: ReadableStream<Uint8Array>;
|
|
128
|
-
public get stderr() {
|
|
161
|
+
public get stderr() {
|
|
162
|
+
return this._stderr;
|
|
163
|
+
}
|
|
129
164
|
|
|
130
165
|
private readonly _exit = new PromiseResolver<number>();
|
|
131
|
-
public get exit() {
|
|
166
|
+
public get exit() {
|
|
167
|
+
return this._exit.promise;
|
|
168
|
+
}
|
|
132
169
|
|
|
133
170
|
public constructor(socket: AdbSocket) {
|
|
134
171
|
this._socket = socket;
|
|
@@ -141,28 +178,45 @@ export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
|
|
|
141
178
|
|
|
142
179
|
const [stdout, stderr] = socket.readable
|
|
143
180
|
.pipeThrough(new StructDeserializeStream(AdbShellProtocolPacket))
|
|
144
|
-
.pipeThrough(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
181
|
+
.pipeThrough(
|
|
182
|
+
new TransformStream<
|
|
183
|
+
AdbShellProtocolPacket,
|
|
184
|
+
AdbShellProtocolPacket
|
|
185
|
+
>({
|
|
186
|
+
transform: (chunk, controller) => {
|
|
187
|
+
if (chunk.id === AdbShellProtocolId.Exit) {
|
|
188
|
+
this._exit.resolve(new Uint8Array(chunk.data)[0]!);
|
|
189
|
+
// We can let `StdoutDeserializeStream` to process `AdbShellProtocolId.Exit`,
|
|
190
|
+
// but since we need this `TransformStream` to capture the exit code anyway,
|
|
191
|
+
// terminating child streams here is killing two birds with one stone.
|
|
192
|
+
controller.terminate();
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
controller.enqueue(chunk);
|
|
196
|
+
},
|
|
197
|
+
})
|
|
198
|
+
)
|
|
157
199
|
.tee();
|
|
158
|
-
this._stdout = stdout
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
200
|
+
this._stdout = stdout.pipeThrough(
|
|
201
|
+
new StdoutDeserializeStream(AdbShellProtocolId.Stdout)
|
|
202
|
+
);
|
|
203
|
+
this._stderr = stderr.pipeThrough(
|
|
204
|
+
new StdoutDeserializeStream(AdbShellProtocolId.Stderr)
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
const multiplexer = new MultiplexStream<
|
|
208
|
+
Consumable<AdbShellProtocolPacketInit>
|
|
209
|
+
>();
|
|
210
|
+
void multiplexer.readable
|
|
211
|
+
.pipeThrough(
|
|
212
|
+
new ConsumableTransformStream({
|
|
213
|
+
async transform(chunk, controller) {
|
|
214
|
+
await controller.enqueue(
|
|
215
|
+
AdbShellProtocolPacket.serialize(chunk)
|
|
216
|
+
);
|
|
217
|
+
},
|
|
218
|
+
})
|
|
219
|
+
)
|
|
166
220
|
.pipeTo(socket.writable);
|
|
167
221
|
|
|
168
222
|
this._stdin = pipeFrom(
|
|
@@ -174,7 +228,7 @@ export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
|
|
|
174
228
|
}
|
|
175
229
|
|
|
176
230
|
public async resize(rows: number, cols: number) {
|
|
177
|
-
await this._socketWriter
|
|
231
|
+
await ConsumableWritableStream.write(this._socketWriter, {
|
|
178
232
|
id: AdbShellProtocolId.WindowSizeChange,
|
|
179
233
|
data: encodeUtf8(
|
|
180
234
|
// The "correct" format is `${rows}x${cols},${x_pixels}x${y_pixels}`
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
Consumable,
|
|
3
|
+
ReadableStream,
|
|
4
|
+
WritableStream,
|
|
5
|
+
} from "@yume-chan/stream-extra";
|
|
6
|
+
import type { ValueOrPromise } from "@yume-chan/struct";
|
|
3
7
|
|
|
4
|
-
import type { Adb } from
|
|
5
|
-
import type { AdbSocket } from
|
|
8
|
+
import type { Adb } from "../../../adb.js";
|
|
9
|
+
import type { AdbSocket } from "../../../socket/index.js";
|
|
6
10
|
|
|
7
11
|
export interface AdbSubprocessProtocol {
|
|
8
12
|
/**
|
|
9
13
|
* A WritableStream that writes to the `stdin` stream.
|
|
10
14
|
*/
|
|
11
|
-
readonly stdin: WritableStream<Uint8Array
|
|
15
|
+
readonly stdin: WritableStream<Consumable<Uint8Array>>;
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
18
|
* The `stdout` stream of the process.
|
|
@@ -56,5 +60,5 @@ export interface AdbSubprocessProtocolConstructor {
|
|
|
56
60
|
raw(adb: Adb, command: string): ValueOrPromise<AdbSubprocessProtocol>;
|
|
57
61
|
|
|
58
62
|
/** Creates a new `AdbShell` by attaching to an exist `AdbSocket` */
|
|
59
|
-
new(socket: AdbSocket): AdbSubprocessProtocol;
|
|
63
|
+
new (socket: AdbSocket): AdbSubprocessProtocol;
|
|
60
64
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
7
|
-
export * from
|
|
1
|
+
export * from "./list.js";
|
|
2
|
+
export * from "./pull.js";
|
|
3
|
+
export * from "./push.js";
|
|
4
|
+
export * from "./request.js";
|
|
5
|
+
export * from "./response.js";
|
|
6
|
+
export * from "./socket.js";
|
|
7
|
+
export * from "./stat.js";
|
|
8
|
+
export * from "./sync.js";
|
|
@@ -1,52 +1,98 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Struct from '@yume-chan/struct';
|
|
1
|
+
import Struct from "@yume-chan/struct";
|
|
3
2
|
|
|
4
|
-
import { AdbSyncRequestId, adbSyncWriteRequest } from
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { AdbSyncRequestId, adbSyncWriteRequest } from "./request.js";
|
|
4
|
+
import { AdbSyncResponseId, adbSyncReadResponses } from "./response.js";
|
|
5
|
+
import type { AdbSyncSocket } from "./socket.js";
|
|
6
|
+
import type { AdbSyncStat } from "./stat.js";
|
|
7
|
+
import { AdbSyncLstatResponse, AdbSyncStatResponse } from "./stat.js";
|
|
7
8
|
|
|
8
9
|
export interface AdbSyncEntry extends AdbSyncStat {
|
|
9
10
|
name: string;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
export const AdbSyncEntryResponse =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
.extra({ id: AdbSyncResponseId.Entry as const });
|
|
13
|
+
export const AdbSyncEntryResponse = new Struct({ littleEndian: true })
|
|
14
|
+
.fields(AdbSyncLstatResponse)
|
|
15
|
+
.uint32("nameLength")
|
|
16
|
+
.string("name", { lengthField: "nameLength" })
|
|
17
|
+
.extra({ id: AdbSyncResponseId.Entry as const });
|
|
18
18
|
|
|
19
|
-
export type AdbSyncEntryResponse =
|
|
19
|
+
export type AdbSyncEntryResponse =
|
|
20
|
+
(typeof AdbSyncEntryResponse)["TDeserializeResult"];
|
|
20
21
|
|
|
21
|
-
export const AdbSyncEntry2Response =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
.extra({ id: AdbSyncResponseId.Entry2 as const });
|
|
22
|
+
export const AdbSyncEntry2Response = new Struct({ littleEndian: true })
|
|
23
|
+
.fields(AdbSyncStatResponse)
|
|
24
|
+
.uint32("nameLength")
|
|
25
|
+
.string("name", { lengthField: "nameLength" })
|
|
26
|
+
.extra({ id: AdbSyncResponseId.Entry2 as const });
|
|
27
27
|
|
|
28
|
-
export type AdbSyncEntry2Response =
|
|
28
|
+
export type AdbSyncEntry2Response =
|
|
29
|
+
(typeof AdbSyncEntry2Response)["TDeserializeResult"];
|
|
30
|
+
|
|
31
|
+
export async function* adbSyncOpenDirV2(
|
|
32
|
+
socket: AdbSyncSocket,
|
|
33
|
+
path: string
|
|
34
|
+
): AsyncGenerator<AdbSyncEntry2Response, void, void> {
|
|
35
|
+
const locked = await socket.lock();
|
|
36
|
+
try {
|
|
37
|
+
await adbSyncWriteRequest(locked, AdbSyncRequestId.ListV2, path);
|
|
38
|
+
for await (const item of adbSyncReadResponses(
|
|
39
|
+
locked,
|
|
40
|
+
AdbSyncResponseId.Entry2,
|
|
41
|
+
AdbSyncEntry2Response
|
|
42
|
+
)) {
|
|
43
|
+
// `LST2` can return error codes for failed `lstat` calls.
|
|
44
|
+
// `LIST` just ignores them.
|
|
45
|
+
// But they only contain `name` so still pretty useless.
|
|
46
|
+
if (item.error !== 0) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
yield item;
|
|
50
|
+
}
|
|
51
|
+
} finally {
|
|
52
|
+
locked.release();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function* adbSyncOpenDirV1(
|
|
57
|
+
socket: AdbSyncSocket,
|
|
58
|
+
path: string
|
|
59
|
+
): AsyncGenerator<AdbSyncEntryResponse, void, void> {
|
|
60
|
+
const locked = await socket.lock();
|
|
61
|
+
try {
|
|
62
|
+
await adbSyncWriteRequest(locked, AdbSyncRequestId.List, path);
|
|
63
|
+
for await (const item of adbSyncReadResponses(
|
|
64
|
+
locked,
|
|
65
|
+
AdbSyncResponseId.Entry,
|
|
66
|
+
AdbSyncEntryResponse
|
|
67
|
+
)) {
|
|
68
|
+
yield item;
|
|
69
|
+
}
|
|
70
|
+
} finally {
|
|
71
|
+
locked.release();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
29
74
|
|
|
30
75
|
export async function* adbSyncOpenDir(
|
|
31
|
-
|
|
32
|
-
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
76
|
+
socket: AdbSyncSocket,
|
|
33
77
|
path: string,
|
|
34
|
-
v2: boolean
|
|
78
|
+
v2: boolean
|
|
35
79
|
): AsyncGenerator<AdbSyncEntry, void, void> {
|
|
36
80
|
if (v2) {
|
|
37
|
-
|
|
38
|
-
yield* adbSyncReadResponses(stream, AdbSyncResponseId.Entry2, AdbSyncEntry2Response);
|
|
81
|
+
yield* adbSyncOpenDirV2(socket, path);
|
|
39
82
|
} else {
|
|
40
|
-
await
|
|
41
|
-
for await (const item of adbSyncReadResponses(stream, AdbSyncResponseId.Entry, AdbSyncEntryResponse)) {
|
|
83
|
+
for await (const item of adbSyncOpenDirV1(socket, path)) {
|
|
42
84
|
// Convert to same format as `AdbSyncEntry2Response` for easier consumption.
|
|
43
85
|
// However it will add some overhead.
|
|
44
86
|
yield {
|
|
45
87
|
mode: item.mode,
|
|
46
88
|
size: BigInt(item.size),
|
|
47
89
|
mtime: BigInt(item.mtime),
|
|
48
|
-
get type() {
|
|
49
|
-
|
|
90
|
+
get type() {
|
|
91
|
+
return item.type;
|
|
92
|
+
},
|
|
93
|
+
get permission() {
|
|
94
|
+
return item.permission;
|
|
95
|
+
},
|
|
50
96
|
name: item.name,
|
|
51
97
|
};
|
|
52
98
|
}
|
|
@@ -1,45 +1,57 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import type { ReadableStream } from "@yume-chan/stream-extra";
|
|
2
|
+
import { PushReadableStream } from "@yume-chan/stream-extra";
|
|
3
|
+
import Struct from "@yume-chan/struct";
|
|
3
4
|
|
|
4
|
-
import { AdbSyncRequestId, adbSyncWriteRequest } from
|
|
5
|
-
import {
|
|
5
|
+
import { AdbSyncRequestId, adbSyncWriteRequest } from "./request.js";
|
|
6
|
+
import { AdbSyncResponseId, adbSyncReadResponses } from "./response.js";
|
|
7
|
+
import type { AdbSyncSocket } from "./socket.js";
|
|
6
8
|
|
|
7
|
-
export const AdbSyncDataResponse =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
.extra({ id: AdbSyncResponseId.Data as const });
|
|
9
|
+
export const AdbSyncDataResponse = new Struct({ littleEndian: true })
|
|
10
|
+
.uint32("dataLength")
|
|
11
|
+
.uint8Array("data", { lengthField: "dataLength" })
|
|
12
|
+
.extra({ id: AdbSyncResponseId.Data as const });
|
|
12
13
|
|
|
13
|
-
export type AdbSyncDataResponse =
|
|
14
|
+
export type AdbSyncDataResponse =
|
|
15
|
+
(typeof AdbSyncDataResponse)["TDeserializeResult"];
|
|
16
|
+
|
|
17
|
+
export async function* adbSyncPullGenerator(
|
|
18
|
+
socket: AdbSyncSocket,
|
|
19
|
+
path: string
|
|
20
|
+
): AsyncGenerator<Uint8Array, void, void> {
|
|
21
|
+
const locked = await socket.lock();
|
|
22
|
+
let done = false;
|
|
23
|
+
try {
|
|
24
|
+
await adbSyncWriteRequest(locked, AdbSyncRequestId.Receive, path);
|
|
25
|
+
for await (const packet of adbSyncReadResponses(
|
|
26
|
+
locked,
|
|
27
|
+
AdbSyncResponseId.Data,
|
|
28
|
+
AdbSyncDataResponse
|
|
29
|
+
)) {
|
|
30
|
+
yield packet.data;
|
|
31
|
+
}
|
|
32
|
+
done = true;
|
|
33
|
+
} finally {
|
|
34
|
+
if (!done) {
|
|
35
|
+
// sync pull can't be cancelled, so we have to read all data
|
|
36
|
+
for await (const packet of adbSyncReadResponses(
|
|
37
|
+
locked,
|
|
38
|
+
AdbSyncResponseId.Data,
|
|
39
|
+
AdbSyncDataResponse
|
|
40
|
+
)) {
|
|
41
|
+
void packet;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
locked.release();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
14
47
|
|
|
15
48
|
export function adbSyncPull(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
path: string,
|
|
49
|
+
socket: AdbSyncSocket,
|
|
50
|
+
path: string
|
|
19
51
|
): ReadableStream<Uint8Array> {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
await adbSyncWriteRequest(writer, AdbSyncRequestId.Receive, path);
|
|
25
|
-
generator = adbSyncReadResponses(stream, AdbSyncResponseId.Data, AdbSyncDataResponse);
|
|
26
|
-
},
|
|
27
|
-
async pull(controller) {
|
|
28
|
-
const { done, value } = await generator.next();
|
|
29
|
-
if (done) {
|
|
30
|
-
controller.close();
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
controller.enqueue(value.data);
|
|
34
|
-
},
|
|
35
|
-
cancel() {
|
|
36
|
-
try {
|
|
37
|
-
generator.return();
|
|
38
|
-
} catch { }
|
|
39
|
-
throw new Error(`Sync commands can't be canceled.`);
|
|
40
|
-
},
|
|
41
|
-
}, {
|
|
42
|
-
highWaterMark: 16 * 1024,
|
|
43
|
-
size(chunk) { return chunk.byteLength; }
|
|
52
|
+
return new PushReadableStream(async (controller) => {
|
|
53
|
+
for await (const data of adbSyncPullGenerator(socket, path)) {
|
|
54
|
+
await controller.enqueue(data);
|
|
55
|
+
}
|
|
44
56
|
});
|
|
45
57
|
}
|