@yume-chan/adb 0.0.15 → 0.0.16
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 +21 -0
- package/CHANGELOG.md +11 -1
- package/LICENSE +21 -21
- package/README.md +247 -247
- package/esm/adb.d.ts +7 -0
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +7 -0
- package/esm/adb.js.map +1 -1
- package/esm/commands/subprocess/protocols/none.d.ts +1 -0
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +6 -5
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/sync/stat.d.ts.map +1 -1
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/socket/dispatcher.d.ts +4 -1
- package/esm/socket/dispatcher.d.ts.map +1 -1
- package/esm/socket/dispatcher.js +11 -8
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/socket/socket.d.ts +6 -1
- package/esm/socket/socket.d.ts.map +1 -1
- package/esm/socket/socket.js +17 -7
- package/esm/socket/socket.js.map +1 -1
- package/esm/stream/buffered.d.ts +6 -2
- package/esm/stream/buffered.d.ts.map +1 -1
- package/esm/stream/buffered.js +67 -47
- package/esm/stream/buffered.js.map +1 -1
- package/esm/stream/detect.js +1 -0
- package/esm/stream/detect.js.map +1 -1
- package/esm/stream/detect.polyfill.d.ts.map +1 -1
- package/esm/stream/detect.polyfill.js +0 -5
- package/esm/stream/detect.polyfill.js.map +1 -1
- package/esm/stream/transform.d.ts +20 -0
- package/esm/stream/transform.d.ts.map +1 -1
- package/esm/stream/transform.js +7 -1
- package/esm/stream/transform.js.map +1 -1
- package/package.json +10 -10
- package/src/adb.ts +280 -273
- package/src/auth.ts +173 -173
- package/src/backend.ts +11 -11
- package/src/commands/base.ts +11 -11
- package/src/commands/framebuffer.ts +73 -73
- package/src/commands/index.ts +8 -8
- package/src/commands/install.ts +30 -30
- package/src/commands/power.ts +54 -54
- package/src/commands/reverse.ts +140 -140
- package/src/commands/subprocess/index.ts +139 -139
- package/src/commands/subprocess/protocols/none.ts +70 -68
- package/src/commands/subprocess/protocols/shell.ts +190 -190
- package/src/commands/subprocess/protocols/types.ts +59 -59
- package/src/commands/subprocess/utils.ts +20 -20
- package/src/commands/sync/index.ts +7 -7
- package/src/commands/sync/list.ts +86 -86
- package/src/commands/sync/pull.ts +46 -46
- package/src/commands/sync/push.ts +41 -41
- package/src/commands/sync/request.ts +50 -50
- package/src/commands/sync/response.ts +64 -64
- package/src/commands/sync/stat.ts +151 -150
- package/src/commands/sync/sync.ts +181 -181
- package/src/commands/tcpip.ts +21 -21
- package/src/crypto.ts +296 -296
- package/src/features.ts +9 -9
- package/src/index.ts +11 -11
- package/src/packet.ts +80 -80
- package/src/socket/dispatcher.ts +305 -304
- package/src/socket/index.ts +2 -2
- package/src/socket/socket.ts +155 -144
- package/src/stream/buffered.ts +168 -147
- package/src/stream/detect.native.ts +362 -362
- package/src/stream/detect.polyfill.ts +22 -28
- package/src/stream/detect.ts +7 -5
- package/src/stream/index.ts +3 -3
- package/src/stream/transform.ts +474 -447
- package/src/utils/auto-reset-event.ts +41 -41
- package/src/utils/base64.ts +306 -306
- package/src/utils/index.ts +3 -3
- package/tsconfig.build.json +3 -3
- package/tsconfig.build.tsbuildinfo +1 -1
- package/tsconfig.test.json +9 -10
- package/web-streams-polyfill-4.0.0-beta.2.tgz +0 -0
- package/esm/commands/subprocess/legacy.d.ts +0 -35
- package/esm/commands/subprocess/legacy.d.ts.map +0 -1
- package/esm/commands/subprocess/legacy.js +0 -53
- package/esm/commands/subprocess/legacy.js.map +0 -1
- package/esm/commands/subprocess/protocol.d.ts +0 -39
- package/esm/commands/subprocess/protocol.d.ts.map +0 -1
- package/esm/commands/subprocess/protocol.js +0 -157
- package/esm/commands/subprocess/protocol.js.map +0 -1
- package/esm/commands/subprocess/types.d.ts +0 -50
- package/esm/commands/subprocess/types.d.ts.map +0 -1
- package/esm/commands/subprocess/types.js +0 -2
- package/esm/commands/subprocess/types.js.map +0 -1
- package/esm/socket/controller.d.ts +0 -37
- package/esm/socket/controller.d.ts.map +0 -1
- package/esm/socket/controller.js +0 -66
- package/esm/socket/controller.js.map +0 -1
- package/esm/stream/detect.bak.d.ts +0 -240
- package/esm/stream/detect.bak.d.ts.map +0 -1
- package/esm/stream/detect.bak.js +0 -60
- package/esm/stream/detect.bak.js.map +0 -1
- package/esm/utils/encoding.d.ts +0 -3
- package/esm/utils/encoding.d.ts.map +0 -1
- package/esm/utils/encoding.js +0 -11
- package/esm/utils/encoding.js.map +0 -1
package/src/socket/socket.ts
CHANGED
|
@@ -1,144 +1,155 @@
|
|
|
1
|
-
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
-
import type { Disposable } from "@yume-chan/event";
|
|
3
|
-
import { AdbCommand } from '../packet.js';
|
|
4
|
-
import { ChunkStream, DuplexStreamFactory, pipeFrom, PushReadableStream, WritableStream, type PushReadableStreamController, type ReadableStream, type ReadableWritablePair } from '../stream/index.js';
|
|
5
|
-
import type { AdbPacketDispatcher, Closeable } from './dispatcher.js';
|
|
6
|
-
|
|
7
|
-
export interface AdbSocketInfo {
|
|
8
|
-
localId: number;
|
|
9
|
-
remoteId: number;
|
|
10
|
-
|
|
11
|
-
localCreated: boolean;
|
|
12
|
-
serviceString: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface AdbSocketConstructionOptions extends AdbSocketInfo {
|
|
16
|
-
dispatcher: AdbPacketDispatcher;
|
|
17
|
-
|
|
18
|
-
highWaterMark?: number | undefined;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<Uint8Array, Uint8Array>, Closeable, Disposable {
|
|
22
|
-
private readonly dispatcher!: AdbPacketDispatcher;
|
|
23
|
-
|
|
24
|
-
public readonly localId!: number;
|
|
25
|
-
public readonly remoteId!: number;
|
|
26
|
-
public readonly localCreated!: boolean;
|
|
27
|
-
public readonly serviceString!: string;
|
|
28
|
-
|
|
29
|
-
private
|
|
30
|
-
|
|
31
|
-
private _readable: ReadableStream<Uint8Array>;
|
|
32
|
-
private _readableController!: PushReadableStreamController<Uint8Array>;
|
|
33
|
-
public get readable() { return this._readable; }
|
|
34
|
-
|
|
35
|
-
private _writePromise: PromiseResolver<void> | undefined;
|
|
36
|
-
public readonly writable: WritableStream<Uint8Array>;
|
|
37
|
-
|
|
38
|
-
private _closed = false;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
public
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
public
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
|
|
1
|
+
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
import type { Disposable } from "@yume-chan/event";
|
|
3
|
+
import { AdbCommand } from '../packet.js';
|
|
4
|
+
import { ChunkStream, DuplexStreamFactory, pipeFrom, PushReadableStream, WritableStream, type PushReadableStreamController, type ReadableStream, type ReadableWritablePair } from '../stream/index.js';
|
|
5
|
+
import type { AdbPacketDispatcher, Closeable } from './dispatcher.js';
|
|
6
|
+
|
|
7
|
+
export interface AdbSocketInfo {
|
|
8
|
+
localId: number;
|
|
9
|
+
remoteId: number;
|
|
10
|
+
|
|
11
|
+
localCreated: boolean;
|
|
12
|
+
serviceString: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface AdbSocketConstructionOptions extends AdbSocketInfo {
|
|
16
|
+
dispatcher: AdbPacketDispatcher;
|
|
17
|
+
|
|
18
|
+
highWaterMark?: number | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class AdbSocketController implements AdbSocketInfo, ReadableWritablePair<Uint8Array, Uint8Array>, Closeable, Disposable {
|
|
22
|
+
private readonly dispatcher!: AdbPacketDispatcher;
|
|
23
|
+
|
|
24
|
+
public readonly localId!: number;
|
|
25
|
+
public readonly remoteId!: number;
|
|
26
|
+
public readonly localCreated!: boolean;
|
|
27
|
+
public readonly serviceString!: string;
|
|
28
|
+
|
|
29
|
+
private _duplex: DuplexStreamFactory<Uint8Array, Uint8Array>;
|
|
30
|
+
|
|
31
|
+
private _readable: ReadableStream<Uint8Array>;
|
|
32
|
+
private _readableController!: PushReadableStreamController<Uint8Array>;
|
|
33
|
+
public get readable() { return this._readable; }
|
|
34
|
+
|
|
35
|
+
private _writePromise: PromiseResolver<void> | undefined;
|
|
36
|
+
public readonly writable: WritableStream<Uint8Array>;
|
|
37
|
+
|
|
38
|
+
private _closed = false;
|
|
39
|
+
/**
|
|
40
|
+
* Whether the socket is half-closed (i.e. the local side initiated the close).
|
|
41
|
+
*
|
|
42
|
+
* It's only used by dispatcher to avoid sending another `CLSE` packet to remote.
|
|
43
|
+
*/
|
|
44
|
+
public get closed() { return this._closed; }
|
|
45
|
+
|
|
46
|
+
private _socket: AdbSocket;
|
|
47
|
+
public get socket() { return this._socket; }
|
|
48
|
+
|
|
49
|
+
public constructor(options: AdbSocketConstructionOptions) {
|
|
50
|
+
Object.assign(this, options);
|
|
51
|
+
|
|
52
|
+
// Check this image to help you understand the stream graph
|
|
53
|
+
// cspell: disable-next-line
|
|
54
|
+
// https://www.plantuml.com/plantuml/png/TL0zoeGm4ErpYc3l5JxyS0yWM6mX5j4C6p4cxcJ25ejttuGX88ZftizxUKmJI275pGhXl0PP_UkfK_CAz5Z2hcWsW9Ny2fdU4C1f5aSchFVxA8vJjlTPRhqZzDQMRB7AklwJ0xXtX0ZSKH1h24ghoKAdGY23FhxC4nS2pDvxzIvxb-8THU0XlEQJ-ZB7SnXTAvc_LhOckhMdLBnbtndpb-SB7a8q2SRD_W00
|
|
55
|
+
|
|
56
|
+
this._duplex = new DuplexStreamFactory<Uint8Array, Uint8Array>({
|
|
57
|
+
close: async () => {
|
|
58
|
+
this._closed = true;
|
|
59
|
+
|
|
60
|
+
await this.dispatcher.sendPacket(
|
|
61
|
+
AdbCommand.Close,
|
|
62
|
+
this.localId,
|
|
63
|
+
this.remoteId
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
// Don't `dispose` here, we need to wait for `CLSE` response packet.
|
|
67
|
+
return false;
|
|
68
|
+
},
|
|
69
|
+
dispose: () => {
|
|
70
|
+
// Error out the pending writes
|
|
71
|
+
this._writePromise?.reject(new Error('Socket closed'));
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
this._readable = this._duplex.wrapReadable(
|
|
76
|
+
new PushReadableStream(controller => {
|
|
77
|
+
this._readableController = controller;
|
|
78
|
+
}, {
|
|
79
|
+
highWaterMark: options.highWaterMark ?? 16 * 1024,
|
|
80
|
+
size(chunk) { return chunk.byteLength; }
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
this.writable = pipeFrom(
|
|
85
|
+
this._duplex.createWritable(
|
|
86
|
+
new WritableStream({
|
|
87
|
+
write: async (chunk) => {
|
|
88
|
+
// Wait for an ack packet
|
|
89
|
+
this._writePromise = new PromiseResolver();
|
|
90
|
+
await this.dispatcher.sendPacket(
|
|
91
|
+
AdbCommand.Write,
|
|
92
|
+
this.localId,
|
|
93
|
+
this.remoteId,
|
|
94
|
+
chunk
|
|
95
|
+
);
|
|
96
|
+
await this._writePromise.promise;
|
|
97
|
+
}
|
|
98
|
+
}),
|
|
99
|
+
),
|
|
100
|
+
new ChunkStream(this.dispatcher.options.maxPayloadSize)
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
this._socket = new AdbSocket(this);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public async enqueue(packet: Uint8Array) {
|
|
107
|
+
// Consumer may abort the `ReadableStream` to close the socket,
|
|
108
|
+
// it's OK to throw away further packets in this case.
|
|
109
|
+
if (this._readableController.abortSignal.aborted) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
await this._readableController.enqueue(packet);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public ack() {
|
|
117
|
+
this._writePromise?.resolve();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public async close(): Promise<void> {
|
|
121
|
+
await this._duplex.close();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public dispose() {
|
|
125
|
+
this._duplex.dispose();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* AdbSocket is a duplex stream.
|
|
131
|
+
*
|
|
132
|
+
* To close it, call either `socket.close()`,
|
|
133
|
+
* `socket.readable.cancel()`, `socket.readable.getReader().cancel()`,
|
|
134
|
+
* `socket.writable.abort()`, `socket.writable.getWriter().abort()`,
|
|
135
|
+
* `socket.writable.close()` or `socket.writable.getWriter().close()`.
|
|
136
|
+
*/
|
|
137
|
+
export class AdbSocket implements AdbSocketInfo, ReadableWritablePair<Uint8Array, Uint8Array>{
|
|
138
|
+
private _controller: AdbSocketController;
|
|
139
|
+
|
|
140
|
+
public get localId(): number { return this._controller.localId; }
|
|
141
|
+
public get remoteId(): number { return this._controller.remoteId; }
|
|
142
|
+
public get localCreated(): boolean { return this._controller.localCreated; }
|
|
143
|
+
public get serviceString(): string { return this._controller.serviceString; }
|
|
144
|
+
|
|
145
|
+
public get readable(): ReadableStream<Uint8Array> { return this._controller.readable; }
|
|
146
|
+
public get writable(): WritableStream<Uint8Array> { return this._controller.writable; }
|
|
147
|
+
|
|
148
|
+
public constructor(controller: AdbSocketController) {
|
|
149
|
+
this._controller = controller;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public close() {
|
|
153
|
+
return this._controller.close();
|
|
154
|
+
}
|
|
155
|
+
}
|
package/src/stream/buffered.ts
CHANGED
|
@@ -1,147 +1,168 @@
|
|
|
1
|
-
import type { StructAsyncDeserializeStream } from '@yume-chan/struct';
|
|
2
|
-
import type { AdbSocket, AdbSocketInfo } from '../socket/index.js';
|
|
3
|
-
import type { ReadableStream, ReadableStreamDefaultReader } from './detect.js';
|
|
4
|
-
import { PushReadableStream } from "./transform.js";
|
|
5
|
-
|
|
6
|
-
export class BufferedStreamEndedError extends Error {
|
|
7
|
-
public constructor() {
|
|
8
|
-
super('Stream ended');
|
|
9
|
-
|
|
10
|
-
// Fix Error's prototype chain when compiling to ES5
|
|
11
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export class BufferedStream {
|
|
16
|
-
private
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
protected readonly
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
index =
|
|
45
|
-
|
|
46
|
-
} else {
|
|
47
|
-
const
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
array.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
array.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
1
|
+
import type { StructAsyncDeserializeStream } from '@yume-chan/struct';
|
|
2
|
+
import type { AdbSocket, AdbSocketInfo } from '../socket/index.js';
|
|
3
|
+
import type { ReadableStream, ReadableStreamDefaultReader } from './detect.js';
|
|
4
|
+
import { PushReadableStream } from "./transform.js";
|
|
5
|
+
|
|
6
|
+
export class BufferedStreamEndedError extends Error {
|
|
7
|
+
public constructor() {
|
|
8
|
+
super('Stream ended');
|
|
9
|
+
|
|
10
|
+
// Fix Error's prototype chain when compiling to ES5
|
|
11
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class BufferedStream {
|
|
16
|
+
private buffered: Uint8Array | undefined;
|
|
17
|
+
private bufferedOffset = 0;
|
|
18
|
+
private bufferedLength = 0;
|
|
19
|
+
|
|
20
|
+
protected readonly stream: ReadableStream<Uint8Array>;
|
|
21
|
+
|
|
22
|
+
protected readonly reader: ReadableStreamDefaultReader<Uint8Array>;
|
|
23
|
+
|
|
24
|
+
public constructor(stream: ReadableStream<Uint8Array>) {
|
|
25
|
+
this.stream = stream;
|
|
26
|
+
this.reader = stream.getReader();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private async readSource() {
|
|
30
|
+
const { done, value } = await this.reader.read();
|
|
31
|
+
if (done) {
|
|
32
|
+
throw new BufferedStreamEndedError();
|
|
33
|
+
}
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private async readAsync(length: number, initial?: Uint8Array) {
|
|
38
|
+
let result: Uint8Array;
|
|
39
|
+
let index: number;
|
|
40
|
+
|
|
41
|
+
if (initial) {
|
|
42
|
+
result = new Uint8Array(length);
|
|
43
|
+
result.set(initial);
|
|
44
|
+
index = initial.byteLength;
|
|
45
|
+
length -= initial.byteLength;
|
|
46
|
+
} else {
|
|
47
|
+
const array = await this.readSource();
|
|
48
|
+
if (array.byteLength === length) {
|
|
49
|
+
return array;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (array.byteLength > length) {
|
|
53
|
+
this.buffered = array;
|
|
54
|
+
this.bufferedOffset = length;
|
|
55
|
+
this.bufferedLength = array.byteLength - length;
|
|
56
|
+
return array.subarray(0, length);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
result = new Uint8Array(length);
|
|
60
|
+
result.set(array);
|
|
61
|
+
index = array.byteLength;
|
|
62
|
+
length -= array.byteLength;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
while (length > 0) {
|
|
66
|
+
const array = await this.readSource();
|
|
67
|
+
if (array.byteLength === length) {
|
|
68
|
+
result.set(array, index);
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (array.byteLength > length) {
|
|
73
|
+
this.buffered = array;
|
|
74
|
+
this.bufferedOffset = length;
|
|
75
|
+
this.bufferedLength = array.byteLength - length;
|
|
76
|
+
result.set(array.subarray(0, length), index);
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
result.set(array, index);
|
|
81
|
+
index += array.byteLength;
|
|
82
|
+
length -= array.byteLength;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
*
|
|
90
|
+
* @param length
|
|
91
|
+
* @returns
|
|
92
|
+
*/
|
|
93
|
+
public read(length: number): Uint8Array | Promise<Uint8Array> {
|
|
94
|
+
// PERF: Add a synchronous path for reading from internal buffer
|
|
95
|
+
if (this.buffered) {
|
|
96
|
+
const array = this.buffered;
|
|
97
|
+
const offset = this.bufferedOffset;
|
|
98
|
+
if (this.bufferedLength > length) {
|
|
99
|
+
// PERF: `subarray` is slow
|
|
100
|
+
// don't use it until absolutely necessary
|
|
101
|
+
this.bufferedOffset += length;
|
|
102
|
+
this.bufferedLength -= length;
|
|
103
|
+
return array.subarray(offset, offset + length);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this.buffered = undefined;
|
|
107
|
+
return this.readAsync(length, array.subarray(offset));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return this.readAsync(length);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Return a readable stream with unconsumed data (if any) and
|
|
115
|
+
* all data from the wrapped stream.
|
|
116
|
+
* @returns A `ReadableStream`
|
|
117
|
+
*/
|
|
118
|
+
public release(): ReadableStream<Uint8Array> {
|
|
119
|
+
if (this.buffered) {
|
|
120
|
+
return new PushReadableStream<Uint8Array>(async controller => {
|
|
121
|
+
// Put the remaining data back to the stream
|
|
122
|
+
await controller.enqueue(this.buffered!);
|
|
123
|
+
|
|
124
|
+
// Manually pipe the stream
|
|
125
|
+
while (true) {
|
|
126
|
+
try {
|
|
127
|
+
const { done, value } = await this.reader.read();
|
|
128
|
+
if (done) {
|
|
129
|
+
controller.close();
|
|
130
|
+
break;
|
|
131
|
+
} else {
|
|
132
|
+
await controller.enqueue(value);
|
|
133
|
+
}
|
|
134
|
+
} catch (e) {
|
|
135
|
+
controller.error(e);
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
} else {
|
|
141
|
+
// Simply release the reader and return the stream
|
|
142
|
+
this.reader.releaseLock();
|
|
143
|
+
return this.stream;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public async close() {
|
|
148
|
+
await this.reader.cancel();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export class AdbBufferedStream
|
|
153
|
+
extends BufferedStream
|
|
154
|
+
implements AdbSocketInfo, StructAsyncDeserializeStream {
|
|
155
|
+
protected readonly socket: AdbSocket;
|
|
156
|
+
|
|
157
|
+
public get localId() { return this.socket.localId; }
|
|
158
|
+
public get remoteId() { return this.socket.remoteId; }
|
|
159
|
+
public get localCreated() { return this.socket.localCreated; }
|
|
160
|
+
public get serviceString() { return this.socket.serviceString; }
|
|
161
|
+
|
|
162
|
+
public get writable() { return this.socket.writable; }
|
|
163
|
+
|
|
164
|
+
public constructor(socket: AdbSocket) {
|
|
165
|
+
super(socket.readable);
|
|
166
|
+
this.socket = socket;
|
|
167
|
+
}
|
|
168
|
+
}
|