diff --git a/packages/ash/assembly/__tests__/echo.spec.ts b/packages/ash/assembly/__tests__/echo.spec.ts index 2a81ea1..b8f7944 100644 --- a/packages/ash/assembly/__tests__/echo.spec.ts +++ b/packages/ash/assembly/__tests__/echo.spec.ts @@ -1,13 +1,13 @@ import { Console, IO, fs, CommandLine } from "../../../assemblyscript/assembly/wasa/mock"; -import { FileDescriptor, File} from "../../../assemblyscript/assembly/wasa/mock/fs"; +import { FileDescriptor, File } from "../../../assemblyscript/assembly/wasa/mock/fs"; import { main } from "../bin/echo"; let Hello = "Hello"; let World = "World"; -function openFile(path: string): FileDescriptor{ - return fs.get(fs.open(path)); +function openFile(path: string): FileDescriptor { + return fs.get(fs.openFile(path)); } function openStdout(): FileDescriptor { @@ -37,9 +37,7 @@ describe("echo", (): void => { stdout.reset(); expect(stdout.readString()).toBe(Hello + " " + World + "\n") stdout.reset(); - expect(stdout.readString()).toBe(stdout2.readString()) - - + expect(stdout.readString()).toBe(stdout2.readString()); }) it("should print no newline with -n", () => { diff --git a/packages/ash/assembly/bin/cat.ts b/packages/ash/assembly/bin/cat.ts new file mode 100644 index 0000000..392f7d8 --- /dev/null +++ b/packages/ash/assembly/bin/cat.ts @@ -0,0 +1,10 @@ + + +export function main(args: string[]): void { + if (args.length > 1) { + for (let i: usize = 1; i < args.length; i++) { + let fd = fs.open(args[i]); + Console.log(fs.readString(fd)) + } + } +} diff --git a/packages/assemblyscript/assembly/__tests__/wasa.spec.ts b/packages/assemblyscript/assembly/__tests__/wasa.spec.ts index 670e3e4..d876a62 100644 --- a/packages/assemblyscript/assembly/__tests__/wasa.spec.ts +++ b/packages/assemblyscript/assembly/__tests__/wasa.spec.ts @@ -1,4 +1,4 @@ -import { Console, IO, fs } from "../wasa/mock"; +import { Console, IO, fs, StringUtils } from "../wasa/mock"; import * as echo from "../bin/echo"; import { JSONDecoder } from "../../node_modules/assemblyscript-json/assembly/decoder"; import { JSONEncoder } from "../../node_modules/assemblyscript-json/assembly/encoder"; @@ -54,7 +54,7 @@ describe("Console", (): void => { "Two non-unique file descriptors points to the same object" ); - stdout = fs.get(fs.open("/dev/fd/1")); + stdout = fs.get(fs.openFile("/dev/fd/1")); expect(stdout.offset).toBe( 0, "A fresh file descriptor has a seek (offset) of 0" @@ -76,3 +76,11 @@ describe("Json", (): void => { roundripTest(jsonStr, jsonStr); }); }); + +describe("readLine", (): void => { + it("should read until newline", (): void => { + let str = "Hello\nWorld"; + let utfStr = str.toUTF8(); + expect(StringUtils.fromCStringTilNewLine(utfStr)).toStrictEqual("Hello\n") + }) +}) diff --git a/packages/assemblyscript/assembly/wasa/mock/fs.ts b/packages/assemblyscript/assembly/wasa/mock/fs.ts index 56d296b..72c5182 100644 --- a/packages/assemblyscript/assembly/wasa/mock/fs.ts +++ b/packages/assemblyscript/assembly/wasa/mock/fs.ts @@ -4,7 +4,7 @@ type path = string; type fd = usize; export class FileDescriptor { - constructor(public file: File, public id: u32, public offset: u32) {} + constructor(public file: File, public id: u32, public offset: u32) { } write(bytes: Array): void { for (let i = 0; i < bytes.length; i++) { @@ -42,11 +42,18 @@ export class FileDescriptor { this.offset = offset; } - readString(): string { - let str = StringUtils.fromCString(this.data + this.offset); - this.offset += str.lengthUTF8 + 1; //For new line + readString(max: usize = 4096): string { + let str = StringUtils.fromCString(this.data + this.offset, max); + this.offset += str.lengthUTF8 + 1; //For null character return str; } + + readLine(max?: usize): string { + let str = StringUtils.fromCStringTilNewLine(this.data + this.offset, max); + this.offset += str.lengthUTF8 + 1; //For null character + return str; + } + /** * Resets the offset to 0 */ @@ -98,16 +105,20 @@ class Directory extends File { children: Array; } + + export class Filesystem { files: Map = new Map(); paths: Map = new Map(); highestFD: usize = 0; + pwd: fd; static Default(): Filesystem { let fs = new Filesystem(); - fs.open("/dev/fd/0") - fs.open("/dev/fd/1") - fs.open("/dev/fd/2") + fs.pwd = fs.openDirectory("/") + fs.openFile("/dev/fd/0") + fs.openFile("/dev/fd/1") + fs.openFile("/dev/fd/2") return fs; } @@ -119,7 +130,7 @@ export class Filesystem { return this.files.get(fd); } - open(path: path): fd { + openFile(path: path): fd { let fd = this.highestFD++; if (!this.paths.has(path)) { this.paths.set(path, new File(path)); @@ -146,4 +157,8 @@ export class Filesystem { close(fd: number): void { this.files.delete(fd); } + openDirectory(path: string): fd { + // this.open() + return 0; + } } diff --git a/packages/assemblyscript/assembly/wasa/mock/index.ts b/packages/assemblyscript/assembly/wasa/mock/index.ts index 112b34b..d40c753 100644 --- a/packages/assemblyscript/assembly/wasa/mock/index.ts +++ b/packages/assemblyscript/assembly/wasa/mock/index.ts @@ -14,7 +14,7 @@ export class Filesystem { * @param dirfd Base directory descriptor (will be automatically set soon) */ static openForRead(path: string, dirfd: Descriptor = 3): Descriptor { - return fs.open(path); + return fs.openFile(path); } /** @@ -23,7 +23,11 @@ export class Filesystem { * @param dirfd Base directory descriptor (will be automatically set soon) */ static openForWrite(path: string, dirfd: Descriptor = 3): Descriptor { - return fs.open(path); + return fs.openFile(path); + } + + static openDirectory(path: string): Descriptor { + return fs.openDirectory(path) } } @@ -77,6 +81,7 @@ export class IO { data: Array = [], chunk_size: usize = 4096 ): Array | null { + fs.get(fd).read(data); return data; } @@ -91,6 +96,7 @@ export class IO { data: Array = [], chunk_size: usize = 4096 ): Array | null { + data.buffer_ = changetype(fs.get(fd).data); return data; } @@ -99,9 +105,15 @@ export class IO { * @param fd file descriptor * @param chunk_size chunk size (default: 4096) */ - static readString(fd: Descriptor, chunk_size: usize = 4096): string | null { - let s = "hello world"; - return s; + static readString(fd: Descriptor, chunk_size: usize = 4096): string { + return fs.get(fd).readString(chunk_size) + } + + /** + * Reach an UTF8 String from a file descriptor until a new line is reached. + */ + static readLine(fd: Descriptor, chunk_size: usize = 4096): string { + return fs.get(fd).readLine(chunk_size) } static reset(fd: Descriptor): void { @@ -226,7 +238,7 @@ export class Process { } export class EnvironEntry { - constructor(readonly key: string, readonly value: string) {} + constructor(readonly key: string, readonly value: string) { } } export class Environ { @@ -288,12 +300,29 @@ export class CommandLine { } } +const newLine: u8 = 10; + export class StringUtils { - static fromCString(cstring: usize): string { - let size = 0; - while (load(cstring + size) != 0) { + static isNewLine(ptr: usize): boolean { + return load(ptr) == newLine; + } + + static fromCString(cstring: usize, max: usize = 4096): string { + let size: usize = 0; + while (load(cstring + size) != 0 && size < max) { size++; } return String.fromUTF8(cstring, size); } + + static fromCStringTilNewLine(cstring: usize, max: usize = 4096): string { + let size: usize = 0; + while (load(cstring + size) != 0 && size < max) { + size++; + if (this.isNewLine(cstring + size - 1)) { + break; + } + } + return String.fromUTF8(cstring, size); + } } diff --git a/packages/assemblyscript/assembly/wasa/mock/path.ts b/packages/assemblyscript/assembly/wasa/mock/path.ts new file mode 100644 index 0000000..8a4238b --- /dev/null +++ b/packages/assemblyscript/assembly/wasa/mock/path.ts @@ -0,0 +1,33 @@ + +const PATH_SEP: string = "/" + +export function basename(path: string): string { + return getPath(path) +} + + +export function dirname(path: string): string { + return getPath(path, 1); +} + +export function getPath(path: string, index: usize = 0): string { + let paths = path.split(PATH_SEP); + let path_index = Math.max(paths.length - 1 - index, 0); + return paths[path_index] +} + + +export function join(paths: string[]): string { + let paths_cleaned = []; + for (let i: usize = 0; i< paths.length; i++){ + let path = paths[i]; + if (path.endsWith('/')) { + path = path.slice(0, paths.length - 1); + } + if (path.startsWith("./")){ + path = path.slice(2) + } + paths_cleaned.push(path) + } + return paths_cleaned.join(PATH_SEP); +} diff --git a/types/assembly/index.d.ts b/types/assembly/index.d.ts index 4409f1f..1e7d0fb 100644 --- a/types/assembly/index.d.ts +++ b/types/assembly/index.d.ts @@ -1524,32 +1524,32 @@ declare abstract class TypedArray implements ArrayBufferView { } /** An array of twos-complement 8-bit signed integers. */ -declare class Int8Array extends TypedArray {} +declare class Int8Array extends TypedArray { } /** An array of 8-bit unsigned integers. */ -declare class Uint8Array extends TypedArray {} +declare class Uint8Array extends TypedArray { } /** A clamped array of 8-bit unsigned integers. */ -declare class Uint8ClampedArray extends TypedArray {} +declare class Uint8ClampedArray extends TypedArray { } /** An array of twos-complement 16-bit signed integers. */ -declare class Int16Array extends TypedArray {} +declare class Int16Array extends TypedArray { } /** An array of 16-bit unsigned integers. */ -declare class Uint16Array extends TypedArray {} +declare class Uint16Array extends TypedArray { } /** An array of twos-complement 32-bit signed integers. */ -declare class Int32Array extends TypedArray {} +declare class Int32Array extends TypedArray { } /** An array of 32-bit unsigned integers. */ -declare class Uint32Array extends TypedArray {} +declare class Uint32Array extends TypedArray { } /** An array of twos-complement 64-bit signed integers. */ -declare class Int64Array extends TypedArray {} +declare class Int64Array extends TypedArray { } /** An array of 64-bit unsigned integers. */ -declare class Uint64Array extends TypedArray {} +declare class Uint64Array extends TypedArray { } /** An array of 32-bit floating point numbers. */ -declare class Float32Array extends TypedArray {} +declare class Float32Array extends TypedArray { } /** An array of 64-bit floating point numbers. */ -declare class Float64Array extends TypedArray {} +declare class Float64Array extends TypedArray { } /** Class representing a sequence of values of type `T`. */ declare class Array { static isArray(value: any): value is Array; - + buffer_: ArrayBuffer [key: number]: T; /** Current length of the array. */ length: i32; @@ -1652,20 +1652,20 @@ declare class Error { } /** Class for indicating an error when a value is not in the set or range of allowed values. */ -declare class RangeError extends Error {} +declare class RangeError extends Error { } /** Class for indicating an error when a value is not of the expected type. */ -declare class TypeError extends Error {} +declare class TypeError extends Error { } /** Class for indicating an error when trying to interpret syntactically invalid code. */ -declare class SyntaxError extends Error {} +declare class SyntaxError extends Error { } -interface Boolean {} -interface Function {} -interface IArguments {} -interface Number {} -interface Object {} -interface RegExp {} +interface Boolean { } +interface Function { } +interface IArguments { } +interface Number { } +interface Object { } +interface RegExp { } declare class Map { readonly size: i32; @@ -1899,10 +1899,10 @@ declare function operator( | "/" | "%" ): ( - target: any, - propertyKey: string, - descriptor: TypedPropertyDescriptor -) => TypedPropertyDescriptor | void; + target: any, + propertyKey: string, + descriptor: TypedPropertyDescriptor + ) => TypedPropertyDescriptor | void; declare namespace operator { /** Annotates a method as a binary operator overload for the specified `token`. */ @@ -1931,26 +1931,26 @@ declare namespace operator { | "/" | "%" ): ( - target: any, - propertyKey: string, - descriptor: TypedPropertyDescriptor - ) => TypedPropertyDescriptor | void; + target: any, + propertyKey: string, + descriptor: TypedPropertyDescriptor + ) => TypedPropertyDescriptor | void; /** Annotates a method as an unary prefix operator overload for the specified `token`. */ export function prefix( token: "!" | "~" | "+" | "-" | "++" | "--" ): ( - target: any, - propertyKey: string, - descriptor: TypedPropertyDescriptor - ) => TypedPropertyDescriptor | void; + target: any, + propertyKey: string, + descriptor: TypedPropertyDescriptor + ) => TypedPropertyDescriptor | void; /** Annotates a method as an unary postfix operator overload for the specified `token`. */ export function postfix( token: "++" | "--" ): ( - target: any, - propertyKey: string, - descriptor: TypedPropertyDescriptor - ) => TypedPropertyDescriptor | void; + target: any, + propertyKey: string, + descriptor: TypedPropertyDescriptor + ) => TypedPropertyDescriptor | void; } /** Annotates a class as being unmanaged with limited capabilities. */ @@ -1971,10 +1971,10 @@ declare function external( namespace: string, name: string ): ( - target: any, - propertyKey: string, - descriptor: TypedPropertyDescriptor -) => TypedPropertyDescriptor | void; + target: any, + propertyKey: string, + descriptor: TypedPropertyDescriptor + ) => TypedPropertyDescriptor | void; /** Annotates a global for lazy compilation. */ declare function lazy( diff --git a/types/wasa/index.d.ts b/types/wasa/index.d.ts index e31ed65..d98eb82 100644 --- a/types/wasa/index.d.ts +++ b/types/wasa/index.d.ts @@ -32,6 +32,7 @@ declare class Console { declare function abort(): void; + declare class CommandLine { static all(): Array static push(s: string): void; @@ -55,6 +56,8 @@ declare class FileDescriptor { pread(bytes: Array): void; readString(): string; + + /** * Resets the offset to 0 */ @@ -82,7 +85,7 @@ declare class Directory extends File { } declare class Filesystem { - files: Map ; + files: Map; paths: Map; static Default(): Filesystem; @@ -100,7 +103,10 @@ declare class Filesystem { readString(fd: fd, offset?: usize): string; writeString(fd: fd, data: string): void; + close(fd: number): void; + + readLine(fd: number, max?: usize): string; } declare var fs: Filesystem;