chore: format code

This commit is contained in:
Simon Chan 2023-02-03 18:02:05 +08:00
parent 0046c76ee1
commit 19ee58ce29
No known key found for this signature in database
GPG key ID: A8B69F750B9BCEDD
12 changed files with 122 additions and 51 deletions

View file

@ -1,5 +1,3 @@
// cspell: ignore libusb
import { PromiseResolver } from "@yume-chan/async"; import { PromiseResolver } from "@yume-chan/async";
import { import {
AbortController, AbortController,
@ -269,6 +267,10 @@ export class Adb implements Closeable {
} }
} }
public supportsFeature(feature: AdbFeatures): boolean {
return this._features.includes(feature);
}
/** /**
* Add a handler for incoming socket. * Add a handler for incoming socket.
* @param handler A function to call with new incoming sockets. It must return `true` if it accepts the socket. * @param handler A function to call with new incoming sockets. It must return `true` if it accepts the socket.

View file

@ -97,9 +97,9 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
const [publicKeyBase64Length] = const [publicKeyBase64Length] =
calculateBase64EncodedLength(publicKeyLength); calculateBase64EncodedLength(publicKeyLength);
// The public key is null terminated, const publicKeyBuffer = new Uint8Array(
// So we allocate the buffer with one extra byte. publicKeyBase64Length + 1 // Null character
const publicKeyBuffer = new Uint8Array(publicKeyBase64Length + 1); );
calculatePublicKey(privateKey, publicKeyBuffer); calculatePublicKey(privateKey, publicKeyBuffer);
encodeBase64(publicKeyBuffer.subarray(0, publicKeyLength), publicKeyBuffer); encodeBase64(publicKeyBuffer.subarray(0, publicKeyLength), publicKeyBuffer);

View file

@ -69,6 +69,6 @@ export async function framebuffer(adb: Adb): Promise<AdbFrameBuffer> {
case 2: case 2:
return AdbFrameBufferV2.deserialize(stream); return AdbFrameBufferV2.deserialize(stream);
default: default:
throw new Error("Unknown FrameBuffer version"); throw new Error("Unsupported FrameBuffer version");
} }
} }

View file

@ -14,16 +14,22 @@ import { type AdbSubprocessProtocol } from "./types.js";
* * `resize`: No * * `resize`: No
*/ */
export class AdbSubprocessNoneProtocol implements AdbSubprocessProtocol { export class AdbSubprocessNoneProtocol implements AdbSubprocessProtocol {
public static isSupported() { return true; } public static isSupported() {
return true;
}
public static async pty(adb: Adb, command: string) { public static async pty(adb: Adb, command: string) {
return new AdbSubprocessNoneProtocol(await adb.createSocket(`shell:${command}`)); return new AdbSubprocessNoneProtocol(
await adb.createSocket(`shell:${command}`)
);
} }
public static async raw(adb: Adb, command: string) { public static async raw(adb: Adb, command: string) {
// `shell,raw:${command}` also triggers raw mode, // `shell,raw:${command}` also triggers raw mode,
// But is not supported on Android version <7. // But is not supported on Android version <7.
return new AdbSubprocessNoneProtocol(await adb.createSocket(`exec:${command}`)); return new AdbSubprocessNoneProtocol(
await adb.createSocket(`exec:${command}`)
);
} }
private readonly socket: AdbSocket; private readonly socket: AdbSocket;
@ -31,22 +37,30 @@ export class AdbSubprocessNoneProtocol implements AdbSubprocessProtocol {
private readonly duplex: DuplexStreamFactory<Uint8Array, Uint8Array>; private readonly duplex: DuplexStreamFactory<Uint8Array, Uint8Array>;
// Legacy shell forwards all data to stdin. // Legacy shell forwards all data to stdin.
public get stdin() { return this.socket.writable; } public get stdin() {
return this.socket.writable;
}
private _stdout: ReadableStream<Uint8Array>; private _stdout: ReadableStream<Uint8Array>;
/** /**
* Legacy shell mixes stdout and stderr. * Legacy shell mixes stdout and stderr.
*/ */
public get stdout() { return this._stdout; } public get stdout() {
return this._stdout;
}
private _stderr: ReadableStream<Uint8Array>; private _stderr: ReadableStream<Uint8Array>;
/** /**
* `stderr` will always be empty. * `stderr` will always be empty.
*/ */
public get stderr() { return this._stderr; } public get stderr() {
return this._stderr;
}
private _exit: Promise<number>; private _exit: Promise<number>;
public get exit() { return this._exit; } public get exit() {
return this._exit;
}
public constructor(socket: AdbSocket) { public constructor(socket: AdbSocket) {
this.socket = socket; this.socket = socket;

View file

@ -13,9 +13,9 @@ import {
import Struct, { placeholder, type StructValueType } from '@yume-chan/struct'; import Struct, { placeholder, type StructValueType } from '@yume-chan/struct';
import { type Adb } from "../../../adb.js"; import { type Adb } from "../../../adb.js";
import { AdbFeatures } from '../../../features.js'; import { AdbFeatures } from "../../../features.js";
import { type AdbSocket } from "../../../socket/index.js"; import { type AdbSocket } from "../../../socket/index.js";
import { encodeUtf8 } from '../../../utils/index.js'; import { encodeUtf8 } from "../../../utils/index.js";
import { type AdbSubprocessProtocol } from "./types.js"; import { type AdbSubprocessProtocol } from "./types.js";
@ -29,17 +29,19 @@ export enum AdbShellProtocolId {
} }
// This packet format is used in both direction. // This packet format is used in both direction.
const AdbShellProtocolPacket = const AdbShellProtocolPacket = new Struct({ littleEndian: true })
new Struct({ littleEndian: true }) .uint8("id", placeholder<AdbShellProtocolId>())
.uint8('id', placeholder<AdbShellProtocolId>()) .uint32("length")
.uint32('length') .uint8Array("data", { lengthField: "length" });
.uint8Array('data', { lengthField: 'length' });
type AdbShellProtocolPacketInit = typeof AdbShellProtocolPacket['TInit']; type AdbShellProtocolPacketInit = typeof AdbShellProtocolPacket["TInit"];
type AdbShellProtocolPacket = StructValueType<typeof AdbShellProtocolPacket>; type AdbShellProtocolPacket = StructValueType<typeof AdbShellProtocolPacket>;
class StdinSerializeStream extends TransformStream<Uint8Array, AdbShellProtocolPacketInit>{ class StdinSerializeStream extends TransformStream<
Uint8Array,
AdbShellProtocolPacketInit
> {
constructor() { constructor() {
super({ super({
transform(chunk, controller) { transform(chunk, controller) {
@ -50,12 +52,15 @@ class StdinSerializeStream extends TransformStream<Uint8Array, AdbShellProtocolP
}, },
flush() { flush() {
// TODO: AdbShellSubprocessProtocol: support closing stdin // TODO: AdbShellSubprocessProtocol: support closing stdin
} },
}); });
} }
} }
class StdoutDeserializeStream extends TransformStream<AdbShellProtocolPacket, Uint8Array>{ class StdoutDeserializeStream extends TransformStream<
AdbShellProtocolPacket,
Uint8Array
> {
constructor(type: AdbShellProtocolId.Stdout | AdbShellProtocolId.Stderr) { constructor(type: AdbShellProtocolId.Stdout | AdbShellProtocolId.Stderr) {
super({ super({
transform(chunk, controller) { transform(chunk, controller) {
@ -116,7 +121,7 @@ class MultiplexStream<T> {
*/ */
export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol { export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
public static isSupported(adb: Adb) { public static isSupported(adb: Adb) {
return adb.features.includes(AdbFeatures.ShellV2); return adb.supportsFeature(AdbFeatures.ShellV2);
} }
public static async pty(adb: Adb, command: string) { public static async pty(adb: Adb, command: string) {

View file

@ -46,21 +46,21 @@ export class AdbSync extends AutoDisposable {
protected sendLock = this.addDisposable(new AutoResetEvent()); protected sendLock = this.addDisposable(new AutoResetEvent());
public get supportsStat(): boolean { public get supportsStat(): boolean {
return this.adb.features.includes(AdbFeatures.StatV2); return this.adb.supportsFeature(AdbFeatures.StatV2);
} }
public get supportsList2(): boolean { public get supportsList2(): boolean {
return this.adb.features.includes(AdbFeatures.ListV2); return this.adb.supportsFeature(AdbFeatures.ListV2);
} }
public get fixedPushMkdir(): boolean { public get fixedPushMkdir(): boolean {
return this.adb.features.includes(AdbFeatures.FixedPushMkdir); return this.adb.supportsFeature(AdbFeatures.FixedPushMkdir);
} }
public get needPushMkdirWorkaround(): boolean { public get needPushMkdirWorkaround(): boolean {
// https://android.googlesource.com/platform/packages/modules/adb/+/91768a57b7138166e0a3d11f79cd55909dda7014/client/file_sync_client.cpp#1361 // https://android.googlesource.com/platform/packages/modules/adb/+/91768a57b7138166e0a3d11f79cd55909dda7014/client/file_sync_client.cpp#1361
return ( return (
this.adb.features.includes(AdbFeatures.ShellV2) && this.adb.supportsFeature(AdbFeatures.ShellV2) &&
!this.fixedPushMkdir !this.fixedPushMkdir
); );
} }
@ -84,7 +84,7 @@ export class AdbSync extends AutoDisposable {
this.supportsStat this.supportsStat
); );
} finally { } finally {
this.sendLock.notify(); this.sendLock.notifyOne();
} }
} }
@ -98,7 +98,7 @@ export class AdbSync extends AutoDisposable {
try { try {
return adbSyncStat(this.stream, this.writer, path); return adbSyncStat(this.stream, this.writer, path);
} finally { } finally {
this.sendLock.notify(); this.sendLock.notifyOne();
} }
} }
@ -124,7 +124,7 @@ export class AdbSync extends AutoDisposable {
this.supportsList2 this.supportsList2
); );
} finally { } finally {
this.sendLock.notify(); this.sendLock.notifyOne();
} }
} }
@ -149,7 +149,7 @@ export class AdbSync extends AutoDisposable {
return adbSyncPull(this.stream, this.writer, filename); return adbSyncPull(this.stream, this.writer, filename);
}, },
close: () => { close: () => {
this.sendLock.notify(); this.sendLock.notifyOne();
}, },
}); });
} }
@ -191,7 +191,7 @@ export class AdbSync extends AutoDisposable {
); );
}, },
close: () => { close: () => {
this.sendLock.notify(); this.sendLock.notifyOne();
}, },
}); });
} }

View file

@ -2,40 +2,39 @@ import { PromiseResolver } from "@yume-chan/async";
import { type Disposable } from "@yume-chan/event"; import { type Disposable } from "@yume-chan/event";
export class AutoResetEvent implements Disposable { export class AutoResetEvent implements Disposable {
private readonly list: PromiseResolver<void>[] = []; private _set: boolean;
private readonly _queue: PromiseResolver<void>[] = [];
private blocking: boolean;
public constructor(initialSet = false) { public constructor(initialSet = false) {
this.blocking = initialSet; this._set = initialSet;
} }
public wait(): Promise<void> { public wait(): Promise<void> {
if (!this.blocking) { if (!this._set) {
this.blocking = true; this._set = true;
if (this.list.length === 0) { if (this._queue.length === 0) {
return Promise.resolve(); return Promise.resolve();
} }
} }
const resolver = new PromiseResolver<void>(); const resolver = new PromiseResolver<void>();
this.list.push(resolver); this._queue.push(resolver);
return resolver.promise; return resolver.promise;
} }
public notify() { public notifyOne() {
if (this.list.length !== 0) { if (this._queue.length !== 0) {
this.list.pop()!.resolve(); this._queue.pop()!.resolve();
} else { } else {
this.blocking = false; this._set = false;
} }
} }
public dispose() { public dispose() {
for (const item of this.list) { for (const item of this._queue) {
item.reject(new Error("The AutoResetEvent has been disposed")); item.reject(new Error("The AutoResetEvent has been disposed"));
} }
this.list.length = 0; this._queue.length = 0;
} }
} }

View file

@ -0,0 +1,45 @@
import { PromiseResolver } from "@yume-chan/async";
import { type Disposable } from "@yume-chan/event";
interface WaitEntry {
condition: () => boolean;
resolver: PromiseResolver<void>;
}
export class ConditionalVariable implements Disposable {
private _locked = false;
private readonly _queue: WaitEntry[] = [];
public wait(condition: () => boolean): Promise<void> {
if (!this._locked) {
this._locked = true;
if (this._queue.length === 0 && condition()) {
return Promise.resolve();
}
}
const resolver = new PromiseResolver<void>();
this._queue.push({ condition, resolver });
return resolver.promise;
}
public notifyOne() {
const entry = this._queue.shift();
if (entry) {
if (entry.condition()) {
entry.resolver.resolve();
}
} else {
this._locked = false;
}
}
public dispose(): void {
for (const item of this._queue) {
item.resolver.reject(
new Error("The ConditionalVariable has been disposed")
);
}
this._queue.length = 0;
}
}

View file

@ -1,3 +1,4 @@
export { decodeUtf8, encodeUtf8 } from '@yume-chan/struct'; export { decodeUtf8, encodeUtf8 } from '@yume-chan/struct';
export * from './auto-reset-event.js'; export * from './auto-reset-event.js';
export * from './base64.js'; export * from './base64.js';
export * from "./conditional-variable.js";

View file

@ -4,7 +4,7 @@
// cspell: ignore systemui // cspell: ignore systemui
// cspell: ignore sysui // cspell: ignore sysui
import { type Adb, AdbCommandBase } from "@yume-chan/adb"; import { AdbCommandBase, type Adb } from "@yume-chan/adb";
import { Settings } from "./settings.js"; import { Settings } from "./settings.js";

View file

@ -2,9 +2,9 @@ import { type Adb } from "@yume-chan/adb";
import { type ScrcpyOptionsInit1_22 } from "../../options/index.js"; import { type ScrcpyOptionsInit1_22 } from "../../options/index.js";
import { import {
type AdbScrcpyConnection,
AdbScrcpyForwardConnection, AdbScrcpyForwardConnection,
AdbScrcpyReverseConnection, AdbScrcpyReverseConnection,
type AdbScrcpyConnection,
} from "../connection.js"; } from "../connection.js";
import { AdbScrcpyOptions1_16 } from "./1_16.js"; import { AdbScrcpyOptions1_16 } from "./1_16.js";

View file

@ -18,8 +18,12 @@ export class BufferedReadableStream {
private bufferedOffset = 0; private bufferedOffset = 0;
private bufferedLength = 0; private bufferedLength = 0;
protected readonly stream: ReadableStream<Uint8Array>; private _position = 0;
public get position() {
return this._position;
}
protected readonly stream: ReadableStream<Uint8Array>;
protected readonly reader: ReadableStreamDefaultReader<Uint8Array>; protected readonly reader: ReadableStreamDefaultReader<Uint8Array>;
public constructor(stream: ReadableStream<Uint8Array>) { public constructor(stream: ReadableStream<Uint8Array>) {
@ -32,6 +36,7 @@ export class BufferedReadableStream {
if (done) { if (done) {
throw new BufferedReadableStreamEndedError(); throw new BufferedReadableStreamEndedError();
} }
this._position += value.byteLength;
return value; return value;
} }