@yume-chan/adb 0.0.13 → 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 +57 -0
- package/CHANGELOG.md +29 -1
- package/LICENSE +21 -21
- package/README.md +247 -247
- package/esm/adb.d.ts +12 -4
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +29 -19
- package/esm/adb.js.map +1 -1
- package/esm/commands/reverse.d.ts +9 -12
- package/esm/commands/reverse.d.ts.map +1 -1
- package/esm/commands/reverse.js +44 -36
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/protocols/none.d.ts +2 -1
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +10 -9
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +6 -3
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/stat.d.ts.map +1 -1
- package/esm/commands/sync/stat.js +2 -2
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.js +1 -1
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/socket/dispatcher.d.ts +25 -14
- package/esm/socket/dispatcher.d.ts.map +1 -1
- package/esm/socket/dispatcher.js +94 -63
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/socket/socket.d.ts +18 -4
- package/esm/socket/socket.d.ts.map +1 -1
- package/esm/socket/socket.js +36 -21
- package/esm/socket/socket.js.map +1 -1
- package/esm/stream/buffered.d.ts +7 -3
- package/esm/stream/buffered.d.ts.map +1 -1
- package/esm/stream/buffered.js +69 -49
- 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 +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 +39 -13
- package/esm/stream/transform.d.ts.map +1 -1
- package/esm/stream/transform.js +67 -90
- package/esm/stream/transform.js.map +1 -1
- package/esm/utils/base64.js +5 -5
- package/esm/utils/base64.js.map +1 -1
- package/package.json +10 -10
- package/src/adb.ts +280 -270
- 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 -136
- 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 -43
- 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 -270
- package/src/socket/index.ts +2 -2
- package/src/socket/socket.ts +155 -136
- 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 -483
- 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
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
import Struct from '@yume-chan/struct';
|
|
2
|
-
import type { AdbBufferedStream, WritableStreamDefaultWriter } from '../../stream/index.js';
|
|
3
|
-
import { AdbSyncRequestId, adbSyncWriteRequest } from './request.js';
|
|
4
|
-
import { AdbSyncDoneResponse, adbSyncReadResponse, AdbSyncResponseId } from './response.js';
|
|
5
|
-
import { AdbSyncLstatResponse, AdbSyncStatResponse, type AdbSyncStat } from './stat.js';
|
|
6
|
-
|
|
7
|
-
export interface AdbSyncEntry extends AdbSyncStat {
|
|
8
|
-
name: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const AdbSyncEntryResponse =
|
|
12
|
-
new Struct({ littleEndian: true })
|
|
13
|
-
.fields(AdbSyncLstatResponse)
|
|
14
|
-
.uint32('nameLength')
|
|
15
|
-
.string('name', { lengthField: 'nameLength' })
|
|
16
|
-
.extra({ id: AdbSyncResponseId.Entry as const });
|
|
17
|
-
|
|
18
|
-
export type AdbSyncEntryResponse = typeof AdbSyncEntryResponse['TDeserializeResult'];
|
|
19
|
-
|
|
20
|
-
export const AdbSyncEntry2Response =
|
|
21
|
-
new Struct({ littleEndian: true })
|
|
22
|
-
.fields(AdbSyncStatResponse)
|
|
23
|
-
.uint32('nameLength')
|
|
24
|
-
.string('name', { lengthField: 'nameLength' })
|
|
25
|
-
.extra({ id: AdbSyncResponseId.Entry2 as const });
|
|
26
|
-
|
|
27
|
-
export type AdbSyncEntry2Response = typeof AdbSyncEntry2Response['TDeserializeResult'];
|
|
28
|
-
|
|
29
|
-
const LIST_V1_RESPONSE_TYPES = {
|
|
30
|
-
[AdbSyncResponseId.Entry]: AdbSyncEntryResponse,
|
|
31
|
-
[AdbSyncResponseId.Done]: new AdbSyncDoneResponse(AdbSyncEntryResponse.size),
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const LIST_V2_RESPONSE_TYPES = {
|
|
35
|
-
[AdbSyncResponseId.Entry2]: AdbSyncEntry2Response,
|
|
36
|
-
[AdbSyncResponseId.Done]: new AdbSyncDoneResponse(AdbSyncEntry2Response.size),
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export async function* adbSyncOpenDir(
|
|
40
|
-
stream: AdbBufferedStream,
|
|
41
|
-
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
42
|
-
path: string,
|
|
43
|
-
v2: boolean,
|
|
44
|
-
): AsyncGenerator<AdbSyncEntry, void, void> {
|
|
45
|
-
let requestId: AdbSyncRequestId.List | AdbSyncRequestId.List2;
|
|
46
|
-
let responseType: typeof LIST_V1_RESPONSE_TYPES | typeof LIST_V2_RESPONSE_TYPES;
|
|
47
|
-
|
|
48
|
-
if (v2) {
|
|
49
|
-
requestId = AdbSyncRequestId.List2;
|
|
50
|
-
responseType = LIST_V2_RESPONSE_TYPES;
|
|
51
|
-
} else {
|
|
52
|
-
requestId = AdbSyncRequestId.List;
|
|
53
|
-
responseType = LIST_V1_RESPONSE_TYPES;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
await adbSyncWriteRequest(writer, requestId, path);
|
|
57
|
-
|
|
58
|
-
while (true) {
|
|
59
|
-
const response = await adbSyncReadResponse(stream, responseType);
|
|
60
|
-
switch (response.id) {
|
|
61
|
-
case AdbSyncResponseId.Entry:
|
|
62
|
-
yield {
|
|
63
|
-
mode: response.mode,
|
|
64
|
-
size: BigInt(response.size),
|
|
65
|
-
mtime: BigInt(response.mtime),
|
|
66
|
-
get type() { return response.type; },
|
|
67
|
-
get permission() { return response.permission; },
|
|
68
|
-
name: response.name,
|
|
69
|
-
};
|
|
70
|
-
break;
|
|
71
|
-
case AdbSyncResponseId.Entry2:
|
|
72
|
-
// `LST2` can return error codes for failed `lstat` calls.
|
|
73
|
-
// `LIST` just ignores them.
|
|
74
|
-
// But they only contain `name` so still pretty useless.
|
|
75
|
-
if (response.error !== 0) {
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
yield response;
|
|
79
|
-
break;
|
|
80
|
-
case AdbSyncResponseId.Done:
|
|
81
|
-
return;
|
|
82
|
-
default:
|
|
83
|
-
throw new Error('Unexpected response id');
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
1
|
+
import Struct from '@yume-chan/struct';
|
|
2
|
+
import type { AdbBufferedStream, WritableStreamDefaultWriter } from '../../stream/index.js';
|
|
3
|
+
import { AdbSyncRequestId, adbSyncWriteRequest } from './request.js';
|
|
4
|
+
import { AdbSyncDoneResponse, adbSyncReadResponse, AdbSyncResponseId } from './response.js';
|
|
5
|
+
import { AdbSyncLstatResponse, AdbSyncStatResponse, type AdbSyncStat } from './stat.js';
|
|
6
|
+
|
|
7
|
+
export interface AdbSyncEntry extends AdbSyncStat {
|
|
8
|
+
name: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const AdbSyncEntryResponse =
|
|
12
|
+
new Struct({ littleEndian: true })
|
|
13
|
+
.fields(AdbSyncLstatResponse)
|
|
14
|
+
.uint32('nameLength')
|
|
15
|
+
.string('name', { lengthField: 'nameLength' })
|
|
16
|
+
.extra({ id: AdbSyncResponseId.Entry as const });
|
|
17
|
+
|
|
18
|
+
export type AdbSyncEntryResponse = typeof AdbSyncEntryResponse['TDeserializeResult'];
|
|
19
|
+
|
|
20
|
+
export const AdbSyncEntry2Response =
|
|
21
|
+
new Struct({ littleEndian: true })
|
|
22
|
+
.fields(AdbSyncStatResponse)
|
|
23
|
+
.uint32('nameLength')
|
|
24
|
+
.string('name', { lengthField: 'nameLength' })
|
|
25
|
+
.extra({ id: AdbSyncResponseId.Entry2 as const });
|
|
26
|
+
|
|
27
|
+
export type AdbSyncEntry2Response = typeof AdbSyncEntry2Response['TDeserializeResult'];
|
|
28
|
+
|
|
29
|
+
const LIST_V1_RESPONSE_TYPES = {
|
|
30
|
+
[AdbSyncResponseId.Entry]: AdbSyncEntryResponse,
|
|
31
|
+
[AdbSyncResponseId.Done]: new AdbSyncDoneResponse(AdbSyncEntryResponse.size),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const LIST_V2_RESPONSE_TYPES = {
|
|
35
|
+
[AdbSyncResponseId.Entry2]: AdbSyncEntry2Response,
|
|
36
|
+
[AdbSyncResponseId.Done]: new AdbSyncDoneResponse(AdbSyncEntry2Response.size),
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export async function* adbSyncOpenDir(
|
|
40
|
+
stream: AdbBufferedStream,
|
|
41
|
+
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
42
|
+
path: string,
|
|
43
|
+
v2: boolean,
|
|
44
|
+
): AsyncGenerator<AdbSyncEntry, void, void> {
|
|
45
|
+
let requestId: AdbSyncRequestId.List | AdbSyncRequestId.List2;
|
|
46
|
+
let responseType: typeof LIST_V1_RESPONSE_TYPES | typeof LIST_V2_RESPONSE_TYPES;
|
|
47
|
+
|
|
48
|
+
if (v2) {
|
|
49
|
+
requestId = AdbSyncRequestId.List2;
|
|
50
|
+
responseType = LIST_V2_RESPONSE_TYPES;
|
|
51
|
+
} else {
|
|
52
|
+
requestId = AdbSyncRequestId.List;
|
|
53
|
+
responseType = LIST_V1_RESPONSE_TYPES;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
await adbSyncWriteRequest(writer, requestId, path);
|
|
57
|
+
|
|
58
|
+
while (true) {
|
|
59
|
+
const response = await adbSyncReadResponse(stream, responseType);
|
|
60
|
+
switch (response.id) {
|
|
61
|
+
case AdbSyncResponseId.Entry:
|
|
62
|
+
yield {
|
|
63
|
+
mode: response.mode,
|
|
64
|
+
size: BigInt(response.size),
|
|
65
|
+
mtime: BigInt(response.mtime),
|
|
66
|
+
get type() { return response.type; },
|
|
67
|
+
get permission() { return response.permission; },
|
|
68
|
+
name: response.name,
|
|
69
|
+
};
|
|
70
|
+
break;
|
|
71
|
+
case AdbSyncResponseId.Entry2:
|
|
72
|
+
// `LST2` can return error codes for failed `lstat` calls.
|
|
73
|
+
// `LIST` just ignores them.
|
|
74
|
+
// But they only contain `name` so still pretty useless.
|
|
75
|
+
if (response.error !== 0) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
yield response;
|
|
79
|
+
break;
|
|
80
|
+
case AdbSyncResponseId.Done:
|
|
81
|
+
return;
|
|
82
|
+
default:
|
|
83
|
+
throw new Error('Unexpected response id');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -1,43 +1,46 @@
|
|
|
1
|
-
import Struct from '@yume-chan/struct';
|
|
2
|
-
import { AdbBufferedStream, ReadableStream, WritableStreamDefaultWriter } from '../../stream/index.js';
|
|
3
|
-
import { AdbSyncRequestId, adbSyncWriteRequest } from './request.js';
|
|
4
|
-
import { AdbSyncDoneResponse, adbSyncReadResponse, AdbSyncResponseId } from './response.js';
|
|
5
|
-
|
|
6
|
-
export const AdbSyncDataResponse =
|
|
7
|
-
new Struct({ littleEndian: true })
|
|
8
|
-
.uint32('dataLength')
|
|
9
|
-
.uint8Array('data', { lengthField: 'dataLength' })
|
|
10
|
-
.extra({ id: AdbSyncResponseId.Data as const });
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
[AdbSyncResponseId.Data]: AdbSyncDataResponse,
|
|
14
|
-
[AdbSyncResponseId.Done]: new AdbSyncDoneResponse(AdbSyncDataResponse.size),
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export function adbSyncPull(
|
|
18
|
-
stream: AdbBufferedStream,
|
|
19
|
-
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
20
|
-
path: string,
|
|
21
|
-
): ReadableStream<Uint8Array> {
|
|
22
|
-
return new ReadableStream<Uint8Array>({
|
|
23
|
-
async start() {
|
|
24
|
-
await adbSyncWriteRequest(writer, AdbSyncRequestId.Receive, path);
|
|
25
|
-
},
|
|
26
|
-
async pull(controller) {
|
|
27
|
-
const response = await adbSyncReadResponse(stream,
|
|
28
|
-
switch (response.id) {
|
|
29
|
-
case AdbSyncResponseId.Data:
|
|
30
|
-
controller.enqueue(response.data!);
|
|
31
|
-
break;
|
|
32
|
-
case AdbSyncResponseId.Done:
|
|
33
|
-
controller.close();
|
|
34
|
-
break;
|
|
35
|
-
default:
|
|
36
|
-
throw new Error('Unexpected response id');
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
1
|
+
import Struct from '@yume-chan/struct';
|
|
2
|
+
import { AdbBufferedStream, ReadableStream, WritableStreamDefaultWriter } from '../../stream/index.js';
|
|
3
|
+
import { AdbSyncRequestId, adbSyncWriteRequest } from './request.js';
|
|
4
|
+
import { AdbSyncDoneResponse, adbSyncReadResponse, AdbSyncResponseId } from './response.js';
|
|
5
|
+
|
|
6
|
+
export const AdbSyncDataResponse =
|
|
7
|
+
new Struct({ littleEndian: true })
|
|
8
|
+
.uint32('dataLength')
|
|
9
|
+
.uint8Array('data', { lengthField: 'dataLength' })
|
|
10
|
+
.extra({ id: AdbSyncResponseId.Data as const });
|
|
11
|
+
|
|
12
|
+
const RESPONSE_TYPES = {
|
|
13
|
+
[AdbSyncResponseId.Data]: AdbSyncDataResponse,
|
|
14
|
+
[AdbSyncResponseId.Done]: new AdbSyncDoneResponse(AdbSyncDataResponse.size),
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function adbSyncPull(
|
|
18
|
+
stream: AdbBufferedStream,
|
|
19
|
+
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
20
|
+
path: string,
|
|
21
|
+
): ReadableStream<Uint8Array> {
|
|
22
|
+
return new ReadableStream<Uint8Array>({
|
|
23
|
+
async start() {
|
|
24
|
+
await adbSyncWriteRequest(writer, AdbSyncRequestId.Receive, path);
|
|
25
|
+
},
|
|
26
|
+
async pull(controller) {
|
|
27
|
+
const response = await adbSyncReadResponse(stream, RESPONSE_TYPES);
|
|
28
|
+
switch (response.id) {
|
|
29
|
+
case AdbSyncResponseId.Data:
|
|
30
|
+
controller.enqueue(response.data!);
|
|
31
|
+
break;
|
|
32
|
+
case AdbSyncResponseId.Done:
|
|
33
|
+
controller.close();
|
|
34
|
+
break;
|
|
35
|
+
default:
|
|
36
|
+
throw new Error('Unexpected response id');
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
cancel() {
|
|
40
|
+
throw new Error(`Sync commands don't support cancel.`);
|
|
41
|
+
},
|
|
42
|
+
}, {
|
|
43
|
+
highWaterMark: 16 * 1024,
|
|
44
|
+
size(chunk) { return chunk.byteLength; }
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
import Struct from '@yume-chan/struct';
|
|
2
|
-
import { AdbBufferedStream, ChunkStream, pipeFrom, WritableStream, WritableStreamDefaultWriter } from '../../stream/index.js';
|
|
3
|
-
import { AdbSyncRequestId, adbSyncWriteRequest } from './request.js';
|
|
4
|
-
import { adbSyncReadResponse, AdbSyncResponseId } from './response.js';
|
|
5
|
-
import { LinuxFileType } from './stat.js';
|
|
6
|
-
|
|
7
|
-
export const AdbSyncOkResponse =
|
|
8
|
-
new Struct({ littleEndian: true })
|
|
9
|
-
.uint32('unused');
|
|
10
|
-
|
|
11
|
-
const ResponseTypes = {
|
|
12
|
-
[AdbSyncResponseId.Ok]: AdbSyncOkResponse,
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const ADB_SYNC_MAX_PACKET_SIZE = 64 * 1024;
|
|
16
|
-
|
|
17
|
-
export function adbSyncPush(
|
|
18
|
-
stream: AdbBufferedStream,
|
|
19
|
-
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
20
|
-
filename: string,
|
|
21
|
-
mode: number = (LinuxFileType.File << 12) | 0o666,
|
|
22
|
-
mtime: number = (Date.now() / 1000) | 0,
|
|
23
|
-
packetSize: number = ADB_SYNC_MAX_PACKET_SIZE,
|
|
24
|
-
): WritableStream<Uint8Array> {
|
|
25
|
-
return pipeFrom(
|
|
26
|
-
new WritableStream<Uint8Array>({
|
|
27
|
-
async start() {
|
|
28
|
-
const pathAndMode = `${filename},${mode.toString()}`;
|
|
29
|
-
await adbSyncWriteRequest(writer, AdbSyncRequestId.Send, pathAndMode);
|
|
30
|
-
},
|
|
31
|
-
async write(chunk) {
|
|
32
|
-
await adbSyncWriteRequest(writer, AdbSyncRequestId.Data, chunk);
|
|
33
|
-
},
|
|
34
|
-
async close() {
|
|
35
|
-
await adbSyncWriteRequest(writer, AdbSyncRequestId.Done, mtime);
|
|
36
|
-
await adbSyncReadResponse(stream, ResponseTypes);
|
|
37
|
-
},
|
|
38
|
-
}),
|
|
39
|
-
new ChunkStream(packetSize)
|
|
40
|
-
);
|
|
41
|
-
}
|
|
1
|
+
import Struct from '@yume-chan/struct';
|
|
2
|
+
import { AdbBufferedStream, ChunkStream, pipeFrom, WritableStream, WritableStreamDefaultWriter } from '../../stream/index.js';
|
|
3
|
+
import { AdbSyncRequestId, adbSyncWriteRequest } from './request.js';
|
|
4
|
+
import { adbSyncReadResponse, AdbSyncResponseId } from './response.js';
|
|
5
|
+
import { LinuxFileType } from './stat.js';
|
|
6
|
+
|
|
7
|
+
export const AdbSyncOkResponse =
|
|
8
|
+
new Struct({ littleEndian: true })
|
|
9
|
+
.uint32('unused');
|
|
10
|
+
|
|
11
|
+
const ResponseTypes = {
|
|
12
|
+
[AdbSyncResponseId.Ok]: AdbSyncOkResponse,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const ADB_SYNC_MAX_PACKET_SIZE = 64 * 1024;
|
|
16
|
+
|
|
17
|
+
export function adbSyncPush(
|
|
18
|
+
stream: AdbBufferedStream,
|
|
19
|
+
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
20
|
+
filename: string,
|
|
21
|
+
mode: number = (LinuxFileType.File << 12) | 0o666,
|
|
22
|
+
mtime: number = (Date.now() / 1000) | 0,
|
|
23
|
+
packetSize: number = ADB_SYNC_MAX_PACKET_SIZE,
|
|
24
|
+
): WritableStream<Uint8Array> {
|
|
25
|
+
return pipeFrom(
|
|
26
|
+
new WritableStream<Uint8Array>({
|
|
27
|
+
async start() {
|
|
28
|
+
const pathAndMode = `${filename},${mode.toString()}`;
|
|
29
|
+
await adbSyncWriteRequest(writer, AdbSyncRequestId.Send, pathAndMode);
|
|
30
|
+
},
|
|
31
|
+
async write(chunk) {
|
|
32
|
+
await adbSyncWriteRequest(writer, AdbSyncRequestId.Data, chunk);
|
|
33
|
+
},
|
|
34
|
+
async close() {
|
|
35
|
+
await adbSyncWriteRequest(writer, AdbSyncRequestId.Done, mtime);
|
|
36
|
+
await adbSyncReadResponse(stream, ResponseTypes);
|
|
37
|
+
},
|
|
38
|
+
}),
|
|
39
|
+
new ChunkStream(packetSize)
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import Struct from '@yume-chan/struct';
|
|
2
|
-
import type { WritableStreamDefaultWriter } from "../../stream/index.js";
|
|
3
|
-
import { encodeUtf8 } from "../../utils/index.js";
|
|
4
|
-
|
|
5
|
-
export enum AdbSyncRequestId {
|
|
6
|
-
List = 'LIST',
|
|
7
|
-
List2 = 'LIS2',
|
|
8
|
-
Send = 'SEND',
|
|
9
|
-
Lstat = 'STAT',
|
|
10
|
-
Stat = 'STA2',
|
|
11
|
-
Lstat2 = 'LST2',
|
|
12
|
-
Data = 'DATA',
|
|
13
|
-
Done = 'DONE',
|
|
14
|
-
Receive = 'RECV',
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const AdbSyncNumberRequest =
|
|
18
|
-
new Struct({ littleEndian: true })
|
|
19
|
-
.string('id', { length: 4 })
|
|
20
|
-
.uint32('arg');
|
|
21
|
-
|
|
22
|
-
export const AdbSyncDataRequest =
|
|
23
|
-
new Struct({ littleEndian: true })
|
|
24
|
-
.fields(AdbSyncNumberRequest)
|
|
25
|
-
.uint8Array('data', { lengthField: 'arg' });
|
|
26
|
-
|
|
27
|
-
export async function adbSyncWriteRequest(
|
|
28
|
-
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
29
|
-
id: AdbSyncRequestId | string,
|
|
30
|
-
value: number | string | Uint8Array
|
|
31
|
-
): Promise<void> {
|
|
32
|
-
let buffer: Uint8Array;
|
|
33
|
-
if (typeof value === 'number') {
|
|
34
|
-
buffer = AdbSyncNumberRequest.serialize({
|
|
35
|
-
id,
|
|
36
|
-
arg: value,
|
|
37
|
-
});
|
|
38
|
-
} else if (typeof value === 'string') {
|
|
39
|
-
buffer = AdbSyncDataRequest.serialize({
|
|
40
|
-
id,
|
|
41
|
-
data: encodeUtf8(value),
|
|
42
|
-
});
|
|
43
|
-
} else {
|
|
44
|
-
buffer = AdbSyncDataRequest.serialize({
|
|
45
|
-
id,
|
|
46
|
-
data: value,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
await writer.write(buffer);
|
|
50
|
-
}
|
|
1
|
+
import Struct from '@yume-chan/struct';
|
|
2
|
+
import type { WritableStreamDefaultWriter } from "../../stream/index.js";
|
|
3
|
+
import { encodeUtf8 } from "../../utils/index.js";
|
|
4
|
+
|
|
5
|
+
export enum AdbSyncRequestId {
|
|
6
|
+
List = 'LIST',
|
|
7
|
+
List2 = 'LIS2',
|
|
8
|
+
Send = 'SEND',
|
|
9
|
+
Lstat = 'STAT',
|
|
10
|
+
Stat = 'STA2',
|
|
11
|
+
Lstat2 = 'LST2',
|
|
12
|
+
Data = 'DATA',
|
|
13
|
+
Done = 'DONE',
|
|
14
|
+
Receive = 'RECV',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const AdbSyncNumberRequest =
|
|
18
|
+
new Struct({ littleEndian: true })
|
|
19
|
+
.string('id', { length: 4 })
|
|
20
|
+
.uint32('arg');
|
|
21
|
+
|
|
22
|
+
export const AdbSyncDataRequest =
|
|
23
|
+
new Struct({ littleEndian: true })
|
|
24
|
+
.fields(AdbSyncNumberRequest)
|
|
25
|
+
.uint8Array('data', { lengthField: 'arg' });
|
|
26
|
+
|
|
27
|
+
export async function adbSyncWriteRequest(
|
|
28
|
+
writer: WritableStreamDefaultWriter<Uint8Array>,
|
|
29
|
+
id: AdbSyncRequestId | string,
|
|
30
|
+
value: number | string | Uint8Array
|
|
31
|
+
): Promise<void> {
|
|
32
|
+
let buffer: Uint8Array;
|
|
33
|
+
if (typeof value === 'number') {
|
|
34
|
+
buffer = AdbSyncNumberRequest.serialize({
|
|
35
|
+
id,
|
|
36
|
+
arg: value,
|
|
37
|
+
});
|
|
38
|
+
} else if (typeof value === 'string') {
|
|
39
|
+
buffer = AdbSyncDataRequest.serialize({
|
|
40
|
+
id,
|
|
41
|
+
data: encodeUtf8(value),
|
|
42
|
+
});
|
|
43
|
+
} else {
|
|
44
|
+
buffer = AdbSyncDataRequest.serialize({
|
|
45
|
+
id,
|
|
46
|
+
data: value,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
await writer.write(buffer);
|
|
50
|
+
}
|
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
import Struct, { type StructAsyncDeserializeStream, type StructLike, type StructValueType } from '@yume-chan/struct';
|
|
2
|
-
import type { AdbBufferedStream } from '../../stream/index.js';
|
|
3
|
-
import { decodeUtf8 } from "../../utils/index.js";
|
|
4
|
-
|
|
5
|
-
export enum AdbSyncResponseId {
|
|
6
|
-
Entry = 'DENT',
|
|
7
|
-
Entry2 = 'DNT2',
|
|
8
|
-
Lstat = 'STAT',
|
|
9
|
-
Stat = 'STA2',
|
|
10
|
-
Lstat2 = 'LST2',
|
|
11
|
-
Done = 'DONE',
|
|
12
|
-
Data = 'DATA',
|
|
13
|
-
Ok = 'OKAY',
|
|
14
|
-
Fail = 'FAIL',
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// DONE responses' size are always same as the request's normal response.
|
|
18
|
-
// For example DONE responses for LIST requests are 16 bytes (same as DENT responses),
|
|
19
|
-
// but DONE responses for STAT requests are 12 bytes (same as STAT responses)
|
|
20
|
-
// So we need to know responses' size in advance.
|
|
21
|
-
export class AdbSyncDoneResponse implements StructLike<AdbSyncDoneResponse> {
|
|
22
|
-
private length: number;
|
|
23
|
-
|
|
24
|
-
public readonly id = AdbSyncResponseId.Done;
|
|
25
|
-
|
|
26
|
-
public constructor(length: number) {
|
|
27
|
-
this.length = length;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public async deserialize(stream: StructAsyncDeserializeStream): Promise<this> {
|
|
31
|
-
await stream.read(this.length);
|
|
32
|
-
return this;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export const AdbSyncFailResponse =
|
|
37
|
-
new Struct({ littleEndian: true })
|
|
38
|
-
.uint32('messageLength')
|
|
39
|
-
.string('message', { lengthField: 'messageLength' })
|
|
40
|
-
.postDeserialize(object => {
|
|
41
|
-
throw new Error(object.message);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
export async function adbSyncReadResponse<T extends Record<string, StructLike<any>>>(
|
|
45
|
-
stream: AdbBufferedStream,
|
|
46
|
-
types: T,
|
|
47
|
-
// When `T` is a union type, `T[keyof T]` only includes their common keys.
|
|
48
|
-
// For example, let `type T = { a: string, b: string } | { a: string, c: string}`,
|
|
49
|
-
// `keyof T` is `'a'`, not `'a' | 'b' | 'c'`.
|
|
50
|
-
// However, `T extends unknown ? keyof T : never` will distribute `T`,
|
|
51
|
-
// so returns all keys.
|
|
52
|
-
): Promise<StructValueType<T extends unknown ? T[keyof T] : never>> {
|
|
53
|
-
const id = decodeUtf8(await stream.read(4));
|
|
54
|
-
|
|
55
|
-
if (id === AdbSyncResponseId.Fail) {
|
|
56
|
-
await AdbSyncFailResponse.deserialize(stream);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (types[id]) {
|
|
60
|
-
return types[id]!.deserialize(stream);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
throw new Error(`Expected '${Object.keys(types).join(', ')}', but got '${id}'`);
|
|
64
|
-
}
|
|
1
|
+
import Struct, { type StructAsyncDeserializeStream, type StructLike, type StructValueType } from '@yume-chan/struct';
|
|
2
|
+
import type { AdbBufferedStream } from '../../stream/index.js';
|
|
3
|
+
import { decodeUtf8 } from "../../utils/index.js";
|
|
4
|
+
|
|
5
|
+
export enum AdbSyncResponseId {
|
|
6
|
+
Entry = 'DENT',
|
|
7
|
+
Entry2 = 'DNT2',
|
|
8
|
+
Lstat = 'STAT',
|
|
9
|
+
Stat = 'STA2',
|
|
10
|
+
Lstat2 = 'LST2',
|
|
11
|
+
Done = 'DONE',
|
|
12
|
+
Data = 'DATA',
|
|
13
|
+
Ok = 'OKAY',
|
|
14
|
+
Fail = 'FAIL',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// DONE responses' size are always same as the request's normal response.
|
|
18
|
+
// For example DONE responses for LIST requests are 16 bytes (same as DENT responses),
|
|
19
|
+
// but DONE responses for STAT requests are 12 bytes (same as STAT responses)
|
|
20
|
+
// So we need to know responses' size in advance.
|
|
21
|
+
export class AdbSyncDoneResponse implements StructLike<AdbSyncDoneResponse> {
|
|
22
|
+
private length: number;
|
|
23
|
+
|
|
24
|
+
public readonly id = AdbSyncResponseId.Done;
|
|
25
|
+
|
|
26
|
+
public constructor(length: number) {
|
|
27
|
+
this.length = length;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public async deserialize(stream: StructAsyncDeserializeStream): Promise<this> {
|
|
31
|
+
await stream.read(this.length);
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const AdbSyncFailResponse =
|
|
37
|
+
new Struct({ littleEndian: true })
|
|
38
|
+
.uint32('messageLength')
|
|
39
|
+
.string('message', { lengthField: 'messageLength' })
|
|
40
|
+
.postDeserialize(object => {
|
|
41
|
+
throw new Error(object.message);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
export async function adbSyncReadResponse<T extends Record<string, StructLike<any>>>(
|
|
45
|
+
stream: AdbBufferedStream,
|
|
46
|
+
types: T,
|
|
47
|
+
// When `T` is a union type, `T[keyof T]` only includes their common keys.
|
|
48
|
+
// For example, let `type T = { a: string, b: string } | { a: string, c: string}`,
|
|
49
|
+
// `keyof T` is `'a'`, not `'a' | 'b' | 'c'`.
|
|
50
|
+
// However, `T extends unknown ? keyof T : never` will distribute `T`,
|
|
51
|
+
// so returns all keys.
|
|
52
|
+
): Promise<StructValueType<T extends unknown ? T[keyof T] : never>> {
|
|
53
|
+
const id = decodeUtf8(await stream.read(4));
|
|
54
|
+
|
|
55
|
+
if (id === AdbSyncResponseId.Fail) {
|
|
56
|
+
await AdbSyncFailResponse.deserialize(stream);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (types[id]) {
|
|
60
|
+
return types[id]!.deserialize(stream);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
throw new Error(`Expected '${Object.keys(types).join(', ')}', but got '${id}'`);
|
|
64
|
+
}
|