UNPKG

@yume-chan/adb

Version:

TypeScript implementation of Android Debug Bridge (ADB) protocol.

81 lines 2.97 kB
import { getUint32LittleEndian } from "@yume-chan/no-data-view"; import { decodeUtf8, string, struct, u32 } from "@yume-chan/struct"; import { unreachable } from "../../utils/no-op.js"; function encodeAsciiUnchecked(value) { 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 * * #__NO_SIDE_EFFECTS__ */ export function adbSyncEncodeId(value) { const buffer = encodeAsciiUnchecked(value); return getUint32LittleEndian(buffer, 0); } export const AdbSyncResponseId = { Entry: adbSyncEncodeId("DENT"), Entry2: adbSyncEncodeId("DNT2"), Lstat: adbSyncEncodeId("STAT"), Stat: adbSyncEncodeId("STA2"), Lstat2: adbSyncEncodeId("LST2"), Done: adbSyncEncodeId("DONE"), Data: adbSyncEncodeId("DATA"), Ok: adbSyncEncodeId("OKAY"), Fail: adbSyncEncodeId("FAIL"), }; export class AdbSyncError extends Error { } export const AdbSyncFailResponse = struct({ message: string(u32) }, { littleEndian: true, postDeserialize(value) { throw new AdbSyncError(value.message); }, }); export async function adbSyncReadResponse(stream, id, type) { 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 '${decodeUtf8(buffer)}'`); } } export async function* adbSyncReadResponses(stream, id, type) { if (typeof id === "string") { id = adbSyncEncodeId(id); } while (true) { const buffer = await stream.readExactly(4); switch (getUint32LittleEndian(buffer, 0)) { case AdbSyncResponseId.Fail: await AdbSyncFailResponse.deserialize(stream); unreachable(); case AdbSyncResponseId.Done: // `DONE` responses' size are always same as the request's normal response. // // For example, `DONE` responses for `LIST` requests are 16 bytes (same as `DENT` responses), // but `DONE` responses for `STAT` requests are 12 bytes (same as `STAT` responses). await stream.readExactly(type.size); return; case id: yield await type.deserialize(stream); break; default: throw new Error(`Expected '${id}' or '${AdbSyncResponseId.Done}', but got '${decodeUtf8(buffer)}'`); } } } //# sourceMappingURL=response.js.map