Loading libraries/adb/src/commands/sync/list.ts +2 −4 Original line number Diff line number Diff line Loading @@ -17,8 +17,7 @@ export interface AdbSyncEntry extends AdbSyncStat { export const AdbSyncEntryResponse = new Struct({ littleEndian: true }) .concat(AdbSyncLstatResponse) .uint32("nameLength") .string("name", { lengthField: "nameLength" }) .extra({ id: AdbSyncResponseId.Entry as const }); .string("name", { lengthField: "nameLength" }); export type AdbSyncEntryResponse = (typeof AdbSyncEntryResponse)["TDeserializeResult"]; Loading @@ -26,8 +25,7 @@ export type AdbSyncEntryResponse = export const AdbSyncEntry2Response = new Struct({ littleEndian: true }) .concat(AdbSyncStatResponse) .uint32("nameLength") .string("name", { lengthField: "nameLength" }) .extra({ id: AdbSyncResponseId.Entry2 as const }); .string("name", { lengthField: "nameLength" }); export type AdbSyncEntry2Response = (typeof AdbSyncEntry2Response)["TDeserializeResult"]; Loading libraries/adb/src/commands/sync/pull.ts +2 −2 Original line number Diff line number Diff line Loading @@ -8,8 +8,7 @@ import type { AdbSyncSocket } from "./socket.js"; export const AdbSyncDataResponse = new Struct({ littleEndian: true }) .uint32("dataLength") .uint8Array("data", { lengthField: "dataLength" }) .extra({ id: AdbSyncResponseId.Data as const }); .uint8Array("data", { lengthField: "dataLength" }); export type AdbSyncDataResponse = (typeof AdbSyncDataResponse)["TDeserializeResult"]; Loading Loading @@ -52,6 +51,7 @@ export function adbSyncPull( socket: AdbSyncSocket, path: string, ): ReadableStream<Uint8Array> { // TODO: use `ReadableStream.from` when it's supported return new PushReadableStream(async (controller) => { for await (const data of adbSyncPullGenerator(socket, path)) { await controller.enqueue(data); Loading libraries/adb/src/commands/sync/push.ts +1 −1 Original line number Diff line number Diff line Loading @@ -111,7 +111,7 @@ export interface AdbSyncPushV2Options extends AdbSyncPushV1Options { } export const AdbSyncSendV2Request = new Struct({ littleEndian: true }) .uint32("id", placeholder<AdbSyncRequestId>()) .uint32("id") .uint32("mode") .uint32("flags", placeholder<AdbSyncSendV2Flags>()); Loading libraries/adb/src/commands/sync/request.ts +21 −16 Original line number Diff line number Diff line Loading @@ -2,21 +2,23 @@ import Struct from "@yume-chan/struct"; import { encodeUtf8 } from "../../utils/index.js"; export enum AdbSyncRequestId { List = "LIST", ListV2 = "LIS2", Send = "SEND", SendV2 = "SND2", Lstat = "STAT", Stat = "STA2", LstatV2 = "LST2", Data = "DATA", Done = "DONE", Receive = "RECV", import { adbSyncEncodeId } from "./response.js"; export namespace AdbSyncRequestId { export const List = adbSyncEncodeId("LIST"); export const ListV2 = adbSyncEncodeId("LIS2"); export const Send = adbSyncEncodeId("SEND"); export const SendV2 = adbSyncEncodeId("SND2"); export const Lstat = adbSyncEncodeId("STAT"); export const Stat = adbSyncEncodeId("STA2"); export const LstatV2 = adbSyncEncodeId("LST2"); export const Data = adbSyncEncodeId("DATA"); export const Done = adbSyncEncodeId("DONE"); export const Receive = adbSyncEncodeId("RECV"); } export const AdbSyncNumberRequest = new Struct({ littleEndian: true }) .string("id", { length: 4 }) .uint32("id") .uint32("arg"); export interface AdbSyncWritable { Loading @@ -25,9 +27,13 @@ export interface AdbSyncWritable { export async function adbSyncWriteRequest( writable: AdbSyncWritable, id: AdbSyncRequestId | string, id: number | string, value: number | string | Uint8Array, ): Promise<void> { if (typeof id === "string") { id = adbSyncEncodeId(id); } if (typeof value === "number") { await writable.write( AdbSyncNumberRequest.serialize({ id, arg: value }), Loading @@ -39,9 +45,8 @@ export async function adbSyncWriteRequest( value = encodeUtf8(value); } // `writable` will copy inputs to an internal buffer, // so we write header and `buffer` separately, // to avoid an extra copy. // `writable` is buffered, it copies inputs to an internal buffer, // so don't concatenate headers and data here, that will be an unnecessary copy. await writable.write( AdbSyncNumberRequest.serialize({ id, arg: value.byteLength }), ); Loading libraries/adb/src/commands/sync/response.ts +47 −18 Original line number Diff line number Diff line import { getUint32LittleEndian } from "@yume-chan/no-data-view"; import type { AsyncExactReadable, StructLike, Loading @@ -7,16 +8,34 @@ import Struct from "@yume-chan/struct"; import { decodeUtf8 } from "../../utils/index.js"; export enum AdbSyncResponseId { Entry = "DENT", Entry2 = "DNT2", Lstat = "STAT", Stat = "STA2", Lstat2 = "LST2", Done = "DONE", Data = "DATA", Ok = "OKAY", Fail = "FAIL", function encodeAsciiUnchecked(value: string): Uint8Array { const result = new Uint8Array(value.length); for (let i = 0; i < value.length; i += 1) { result[i] = value.charCodeAt(i); } return result; } /** * Encode ID to numbers for faster comparison * @param value A 4-character string * @returns A 32-bit integer by encoding the string as little-endian */ export function adbSyncEncodeId(value: string): number { const buffer = encodeAsciiUnchecked(value); return getUint32LittleEndian(buffer, 0); } export namespace AdbSyncResponseId { export const Entry = adbSyncEncodeId("DENT"); export const Entry2 = adbSyncEncodeId("DNT2"); export const Lstat = adbSyncEncodeId("STAT"); export const Stat = adbSyncEncodeId("STA2"); export const Lstat2 = adbSyncEncodeId("LST2"); export const Done = adbSyncEncodeId("DONE"); export const Data = adbSyncEncodeId("DATA"); export const Ok = adbSyncEncodeId("OKAY"); export const Fail = adbSyncEncodeId("FAIL"); } export class AdbSyncError extends Error {} Loading @@ -30,18 +49,24 @@ export const AdbSyncFailResponse = new Struct({ littleEndian: true }) export async function adbSyncReadResponse<T>( stream: AsyncExactReadable, id: AdbSyncResponseId, id: number | string, type: StructLike<T>, ): Promise<T> { const actualId = decodeUtf8(await stream.readExactly(4)); switch (actualId) { if (typeof id === "string") { id = adbSyncEncodeId(id); } const buffer = await stream.readExactly(4); switch (getUint32LittleEndian(buffer, 0)) { case AdbSyncResponseId.Fail: await AdbSyncFailResponse.deserialize(stream); throw new Error("Unreachable"); case id: return await type.deserialize(stream); default: throw new Error(`Expected '${id}', but got '${actualId}'`); throw new Error( `Expected '${id}', but got '${decodeUtf8(buffer)}'`, ); } } Loading @@ -49,12 +74,16 @@ export async function* adbSyncReadResponses< T extends Struct<object, PropertyKey, object, unknown>, >( stream: AsyncExactReadable, id: AdbSyncResponseId, id: number | string, type: T, ): AsyncGenerator<StructValueType<T>, void, void> { if (typeof id === "string") { id = adbSyncEncodeId(id); } while (true) { const actualId = decodeUtf8(await stream.readExactly(4)); switch (actualId) { const buffer = await stream.readExactly(4); switch (getUint32LittleEndian(buffer, 0)) { case AdbSyncResponseId.Fail: await AdbSyncFailResponse.deserialize(stream); throw new Error("Unreachable"); Loading @@ -70,7 +99,7 @@ export async function* adbSyncReadResponses< break; default: throw new Error( `Expected '${id}' or '${AdbSyncResponseId.Done}', but got '${actualId}'`, `Expected '${id}' or '${AdbSyncResponseId.Done}', but got '${decodeUtf8(buffer)}'`, ); } } Loading Loading
libraries/adb/src/commands/sync/list.ts +2 −4 Original line number Diff line number Diff line Loading @@ -17,8 +17,7 @@ export interface AdbSyncEntry extends AdbSyncStat { export const AdbSyncEntryResponse = new Struct({ littleEndian: true }) .concat(AdbSyncLstatResponse) .uint32("nameLength") .string("name", { lengthField: "nameLength" }) .extra({ id: AdbSyncResponseId.Entry as const }); .string("name", { lengthField: "nameLength" }); export type AdbSyncEntryResponse = (typeof AdbSyncEntryResponse)["TDeserializeResult"]; Loading @@ -26,8 +25,7 @@ export type AdbSyncEntryResponse = export const AdbSyncEntry2Response = new Struct({ littleEndian: true }) .concat(AdbSyncStatResponse) .uint32("nameLength") .string("name", { lengthField: "nameLength" }) .extra({ id: AdbSyncResponseId.Entry2 as const }); .string("name", { lengthField: "nameLength" }); export type AdbSyncEntry2Response = (typeof AdbSyncEntry2Response)["TDeserializeResult"]; Loading
libraries/adb/src/commands/sync/pull.ts +2 −2 Original line number Diff line number Diff line Loading @@ -8,8 +8,7 @@ import type { AdbSyncSocket } from "./socket.js"; export const AdbSyncDataResponse = new Struct({ littleEndian: true }) .uint32("dataLength") .uint8Array("data", { lengthField: "dataLength" }) .extra({ id: AdbSyncResponseId.Data as const }); .uint8Array("data", { lengthField: "dataLength" }); export type AdbSyncDataResponse = (typeof AdbSyncDataResponse)["TDeserializeResult"]; Loading Loading @@ -52,6 +51,7 @@ export function adbSyncPull( socket: AdbSyncSocket, path: string, ): ReadableStream<Uint8Array> { // TODO: use `ReadableStream.from` when it's supported return new PushReadableStream(async (controller) => { for await (const data of adbSyncPullGenerator(socket, path)) { await controller.enqueue(data); Loading
libraries/adb/src/commands/sync/push.ts +1 −1 Original line number Diff line number Diff line Loading @@ -111,7 +111,7 @@ export interface AdbSyncPushV2Options extends AdbSyncPushV1Options { } export const AdbSyncSendV2Request = new Struct({ littleEndian: true }) .uint32("id", placeholder<AdbSyncRequestId>()) .uint32("id") .uint32("mode") .uint32("flags", placeholder<AdbSyncSendV2Flags>()); Loading
libraries/adb/src/commands/sync/request.ts +21 −16 Original line number Diff line number Diff line Loading @@ -2,21 +2,23 @@ import Struct from "@yume-chan/struct"; import { encodeUtf8 } from "../../utils/index.js"; export enum AdbSyncRequestId { List = "LIST", ListV2 = "LIS2", Send = "SEND", SendV2 = "SND2", Lstat = "STAT", Stat = "STA2", LstatV2 = "LST2", Data = "DATA", Done = "DONE", Receive = "RECV", import { adbSyncEncodeId } from "./response.js"; export namespace AdbSyncRequestId { export const List = adbSyncEncodeId("LIST"); export const ListV2 = adbSyncEncodeId("LIS2"); export const Send = adbSyncEncodeId("SEND"); export const SendV2 = adbSyncEncodeId("SND2"); export const Lstat = adbSyncEncodeId("STAT"); export const Stat = adbSyncEncodeId("STA2"); export const LstatV2 = adbSyncEncodeId("LST2"); export const Data = adbSyncEncodeId("DATA"); export const Done = adbSyncEncodeId("DONE"); export const Receive = adbSyncEncodeId("RECV"); } export const AdbSyncNumberRequest = new Struct({ littleEndian: true }) .string("id", { length: 4 }) .uint32("id") .uint32("arg"); export interface AdbSyncWritable { Loading @@ -25,9 +27,13 @@ export interface AdbSyncWritable { export async function adbSyncWriteRequest( writable: AdbSyncWritable, id: AdbSyncRequestId | string, id: number | string, value: number | string | Uint8Array, ): Promise<void> { if (typeof id === "string") { id = adbSyncEncodeId(id); } if (typeof value === "number") { await writable.write( AdbSyncNumberRequest.serialize({ id, arg: value }), Loading @@ -39,9 +45,8 @@ export async function adbSyncWriteRequest( value = encodeUtf8(value); } // `writable` will copy inputs to an internal buffer, // so we write header and `buffer` separately, // to avoid an extra copy. // `writable` is buffered, it copies inputs to an internal buffer, // so don't concatenate headers and data here, that will be an unnecessary copy. await writable.write( AdbSyncNumberRequest.serialize({ id, arg: value.byteLength }), ); Loading
libraries/adb/src/commands/sync/response.ts +47 −18 Original line number Diff line number Diff line import { getUint32LittleEndian } from "@yume-chan/no-data-view"; import type { AsyncExactReadable, StructLike, Loading @@ -7,16 +8,34 @@ import Struct from "@yume-chan/struct"; import { decodeUtf8 } from "../../utils/index.js"; export enum AdbSyncResponseId { Entry = "DENT", Entry2 = "DNT2", Lstat = "STAT", Stat = "STA2", Lstat2 = "LST2", Done = "DONE", Data = "DATA", Ok = "OKAY", Fail = "FAIL", function encodeAsciiUnchecked(value: string): Uint8Array { const result = new Uint8Array(value.length); for (let i = 0; i < value.length; i += 1) { result[i] = value.charCodeAt(i); } return result; } /** * Encode ID to numbers for faster comparison * @param value A 4-character string * @returns A 32-bit integer by encoding the string as little-endian */ export function adbSyncEncodeId(value: string): number { const buffer = encodeAsciiUnchecked(value); return getUint32LittleEndian(buffer, 0); } export namespace AdbSyncResponseId { export const Entry = adbSyncEncodeId("DENT"); export const Entry2 = adbSyncEncodeId("DNT2"); export const Lstat = adbSyncEncodeId("STAT"); export const Stat = adbSyncEncodeId("STA2"); export const Lstat2 = adbSyncEncodeId("LST2"); export const Done = adbSyncEncodeId("DONE"); export const Data = adbSyncEncodeId("DATA"); export const Ok = adbSyncEncodeId("OKAY"); export const Fail = adbSyncEncodeId("FAIL"); } export class AdbSyncError extends Error {} Loading @@ -30,18 +49,24 @@ export const AdbSyncFailResponse = new Struct({ littleEndian: true }) export async function adbSyncReadResponse<T>( stream: AsyncExactReadable, id: AdbSyncResponseId, id: number | string, type: StructLike<T>, ): Promise<T> { const actualId = decodeUtf8(await stream.readExactly(4)); switch (actualId) { if (typeof id === "string") { id = adbSyncEncodeId(id); } const buffer = await stream.readExactly(4); switch (getUint32LittleEndian(buffer, 0)) { case AdbSyncResponseId.Fail: await AdbSyncFailResponse.deserialize(stream); throw new Error("Unreachable"); case id: return await type.deserialize(stream); default: throw new Error(`Expected '${id}', but got '${actualId}'`); throw new Error( `Expected '${id}', but got '${decodeUtf8(buffer)}'`, ); } } Loading @@ -49,12 +74,16 @@ export async function* adbSyncReadResponses< T extends Struct<object, PropertyKey, object, unknown>, >( stream: AsyncExactReadable, id: AdbSyncResponseId, id: number | string, type: T, ): AsyncGenerator<StructValueType<T>, void, void> { if (typeof id === "string") { id = adbSyncEncodeId(id); } while (true) { const actualId = decodeUtf8(await stream.readExactly(4)); switch (actualId) { const buffer = await stream.readExactly(4); switch (getUint32LittleEndian(buffer, 0)) { case AdbSyncResponseId.Fail: await AdbSyncFailResponse.deserialize(stream); throw new Error("Unreachable"); Loading @@ -70,7 +99,7 @@ export async function* adbSyncReadResponses< break; default: throw new Error( `Expected '${id}' or '${AdbSyncResponseId.Done}', but got '${actualId}'`, `Expected '${id}' or '${AdbSyncResponseId.Done}', but got '${decodeUtf8(buffer)}'`, ); } } Loading