2020-03-03 08:56:10 -05:00
|
|
|
import Dirent from "./_fs_dirent.ts";
|
2020-04-20 05:29:37 -04:00
|
|
|
import { assert } from "../../testing/asserts.ts";
|
2020-03-03 08:56:10 -05:00
|
|
|
|
|
|
|
export default class Dir {
|
|
|
|
private dirPath: string | Uint8Array;
|
2020-04-16 15:45:30 -04:00
|
|
|
private syncIterator!: Iterator<Deno.DirEntry> | null;
|
|
|
|
private asyncIterator!: AsyncIterator<Deno.DirEntry> | null;
|
2020-03-03 08:56:10 -05:00
|
|
|
|
|
|
|
constructor(path: string | Uint8Array) {
|
|
|
|
this.dirPath = path;
|
|
|
|
}
|
|
|
|
|
|
|
|
get path(): string {
|
|
|
|
if (this.dirPath instanceof Uint8Array) {
|
|
|
|
return new TextDecoder().decode(this.dirPath);
|
|
|
|
}
|
|
|
|
return this.dirPath;
|
|
|
|
}
|
|
|
|
|
|
|
|
read(callback?: Function): Promise<Dirent | null> {
|
2020-04-20 05:29:37 -04:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
if (!this.asyncIterator) {
|
|
|
|
this.asyncIterator = Deno.readdir(this.path)[Symbol.asyncIterator]();
|
2020-03-03 08:56:10 -05:00
|
|
|
}
|
2020-04-20 05:29:37 -04:00
|
|
|
assert(this.asyncIterator);
|
|
|
|
this.asyncIterator
|
|
|
|
.next()
|
|
|
|
.then(({ value }) => {
|
|
|
|
resolve(value ? value : null);
|
|
|
|
if (callback) {
|
|
|
|
callback(null, value ? value : null);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
if (callback) {
|
|
|
|
callback(err, null);
|
|
|
|
}
|
|
|
|
reject(err);
|
|
|
|
});
|
2020-03-03 08:56:10 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
readSync(): Dirent | null {
|
2020-04-16 15:45:30 -04:00
|
|
|
if (!this.syncIterator) {
|
|
|
|
this.syncIterator = Deno.readdirSync(this.path)![Symbol.iterator]();
|
2020-03-03 08:56:10 -05:00
|
|
|
}
|
|
|
|
|
2020-04-16 15:45:30 -04:00
|
|
|
const file: Deno.DirEntry = this.syncIterator.next().value;
|
2020-03-03 08:56:10 -05:00
|
|
|
|
2020-04-16 15:45:30 -04:00
|
|
|
return file ? new Dirent(file) : null;
|
2020-03-03 08:56:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unlike Node, Deno does not require managing resource ids for reading
|
|
|
|
* directories, and therefore does not need to close directories when
|
|
|
|
* finished reading.
|
|
|
|
*/
|
|
|
|
close(callback?: Function): Promise<void> {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
try {
|
|
|
|
if (callback) {
|
|
|
|
callback(null);
|
|
|
|
}
|
|
|
|
resolve();
|
|
|
|
} catch (err) {
|
|
|
|
if (callback) {
|
|
|
|
callback(err);
|
|
|
|
}
|
|
|
|
reject(err);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unlike Node, Deno does not require managing resource ids for reading
|
|
|
|
* directories, and therefore does not need to close directories when
|
|
|
|
* finished reading
|
|
|
|
*/
|
|
|
|
closeSync(): void {
|
|
|
|
//No op
|
|
|
|
}
|
|
|
|
|
|
|
|
async *[Symbol.asyncIterator](): AsyncIterableIterator<Dirent> {
|
|
|
|
try {
|
|
|
|
while (true) {
|
|
|
|
const dirent: Dirent | null = await this.read();
|
|
|
|
if (dirent === null) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
yield dirent;
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
await this.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|