Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/ash/assembly/__tests__/echo.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ describe("echo", (): void => {
echo(CommandLine.all())
let str = Hello + " " + World + "\n";
let stdoutStr = readString(stdout)
expect<u32>(Console.stdout.tell()).toBe(str.lengthUTF8, "Two extra characters for space and \\n")
expect<u32>(Console.stdout.tell()).toBe(str.lengthUTF8)
Console.stdout.reset();
expect<string>(readString(Console.stdout)).toBe(Hello + " " + World + "\n")
Console.stdout.reset();
expect<string>(readString(Console.stdout)).toBe(stdoutStr);
})
});

it("should print no newline with -n", () => {
CommandLine.push("-n")
CommandLine.push(Hello)
CommandLine.push(World)
echo(CommandLine.all())
let str = Hello + " " + World;
expect<u32>(Console.stdout.tell()).toBe(str.lengthUTF8 + 1, "Two extra characters for space and \\n")
expect<u32>(Console.stdout.tell()).toBe(str.lengthUTF8)
Console.stdout.reset();
expect<string>(Console.stdout.readString().result).toBe(str)
Console.stdout.reset();
Expand Down
42 changes: 40 additions & 2 deletions packages/assemblyscript/assembly/__tests__/wasa.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,16 @@ describe("readLine", (): void => {
expect<string>(StringUtils.fromCStringTilNewLine(utfStr, str.lengthUTF8)).toStrictEqual("Hello\n")
});

it("should read return null after no more lines", (): void => {
it("should read null when reading from a terminating char", (): void => {
let str = "Hello World";
let utfStr = str.toUTF8();
expect<string>(StringUtils.fromCStringTilNewLine(utfStr, str.lengthUTF8 - 2)).toBeNull();
expect<string>(StringUtils.fromCStringTilNewLine(utfStr + str.lengthUTF8, str.lengthUTF8)).toBeNull();
});

it("should read chunk", () => {
let hello = "Hello ";
let world = hello + "World";
expect<string>(StringUtils.fromCString(world.toUTF8(), hello.lengthUTF8)).toStrictEqual(hello);
});
});

Expand Down Expand Up @@ -86,3 +92,35 @@ describe("Open", (): void => {
});

});

describe("read", (): void => {
it("read string should return error if offset is at the eof", () => {
let file = _fs.createFile("./tmp");
file.result.erase();
expect<Wasi.errno>(file.result.readString().error).toBe(Wasi.errno.NOMEM);
});
})

let file: FileDescriptor;
describe("write", (): void => {

beforeEach(() => {
file = _fs.createFile("./tmp").result;
file.erase();
});

it("should update size after a write", () => {
expect<usize>(file.size).toBe(0);
let str = "hello world";
expect<Wasi.errno>(file.writeString("hello world")).toBe(Wasi.errno.SUCCESS)
expect<usize>(file.size).toBe(str.lengthUTF8);
});

it("should not update size if offset is less than size", (): void => {
let str = "hello world";
expect<Wasi.errno>(file.writeString("hello world")).toBe(Wasi.errno.SUCCESS)
file.reset();
expect<Wasi.errno>(file.writeString("HELLO")).toBe(Wasi.errno.SUCCESS)
expect<usize>(file.size).toBe(str.lengthUTF8);
})
})
78 changes: 58 additions & 20 deletions packages/assemblyscript/assembly/wasa/mock/fs/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,24 @@ export class FileDescriptor {
constructor(public fd: fd, public file: File | null, public offset: usize = 0) { }

write(bytes: Array<u8>): Wasi.errno {
if (bytes.length + this.offset > this.length) {
return Wasi.errno.NOMEM
let res = this.file!.writeBytes(this.offset, bytes.buffer_.data, bytes.length);
if (res == Wasi.errno.SUCCESS) {
this.offset += bytes.length;
}
memory.copy(this.data + this.offset, bytes.buffer_.data, bytes.length)
this.offset += bytes.length;
return Wasi.errno.SUCCESS;
return res;
}

writeString(str: string, newline: boolean = false): Wasi.errno {
// TODO: Add error checking
let _str = str + (newline ? "\n" : "");
if (_str.lengthUTF8 as usize + this.offset > this.length) {
return Wasi.errno.NOMEM
let res = this.file!.writeBytes(this.offset, _str.toUTF8(), _str.lengthUTF8);
if (res == Wasi.errno.SUCCESS) {
this.offset += _str.lengthUTF8;
}
memory.copy(this.data + this.offset, _str.toUTF8(), _str.lengthUTF8);
this.offset += str.lengthUTF8 + 1;
return Wasi.errno.SUCCESS;
return res;
}


read(bytes: Array<u8>): Wasi.errno {
if (!this.hasSpace(bytes)) {
return Wasi.errno.NOMEM;
Expand All @@ -57,16 +56,19 @@ export class FileDescriptor {
}

readString(max: usize = 4096): WasiResult<string> {
let str = StringUtils.fromCString(this.data + this.offset, this.length - this.offset);
let _max = <usize>Math.min(max, this.length - this.offset);
let str = StringUtils.fromCString(this.data + this.offset, _max);
log<string>(str);
if (str == null) {
return WasiResult.fail<string>(Wasi.errno.NOMEM)
}
this.offset += str.lengthUTF8 + 1; //For null character
this.offset += str.lengthUTF8; //For null character
return WasiResult.resolve<string>(str);
}

readLine(): WasiResult<string> {
let str = StringUtils.fromCStringTilNewLine(this.data + this.offset, this.length - this.offset);
readLine(max: usize = 4096): WasiResult<string> {
let _max = <usize>Math.min(max, this.length - this.offset);
let str = StringUtils.fromCStringTilNewLine(this.data + this.offset, _max);
if (str == null) {
return WasiResult.fail<string>(Wasi.errno.NOMEM)
}
Expand All @@ -92,7 +94,7 @@ export class FileDescriptor {
break;
}
case Wasi.whence.END: {
newOffset = <usize>(this.length - <u64>Math.abs(<f64>offset));
newOffset = <usize>(this.size - <u64>Math.abs(<f64>offset));
break;
}
case Wasi.whence.SET: {
Expand Down Expand Up @@ -147,6 +149,11 @@ export class FileDescriptor {
}
return Wasi.errno.NOMEM;
}

get size(): usize {
return this.file!.size;
}

}

export class DirectoryDescriptor extends FileDescriptor {
Expand All @@ -162,7 +169,8 @@ export class DirectoryDescriptor extends FileDescriptor {
listDir(): DirectoryEntry[] {
let files = new Array<DirectoryEntry>();
for (let i: i32 = 0; i < this.children.length; i++) {
files.push(new DirectoryEntry(path.basename(this.children[i].path), this.children[i].type))
let child = this.children[i];
files.push(new DirectoryEntry(path.basename(child.path), child.type, child.size))
}
return files;
}
Expand All @@ -175,8 +183,11 @@ export class DirectoryDescriptor extends FileDescriptor {
export class File {
private _data: ArrayBuffer;
static DefaultSize: u32 = 1024;
size: usize = 0;

constructor(public path: string, public type: Wasi.filetype = Wasi.filetype.REGULAR_FILE) {
this._data = new ArrayBuffer(File.DefaultSize);
this.writeEOT(0);
}
/**
*
Expand Down Expand Up @@ -206,13 +217,40 @@ export class File {

erase(): Wasi.errno {
this._data = new ArrayBuffer(File.DefaultSize);
this.size = 0;
this.writeEOT(0);
return Wasi.errno.SUCCESS;
}

get length(): usize {
return this._data.byteLength;
}

writeEOT(offset: usize): Wasi.errno {
return this.writeByte(offset, StringUtils.EOT);
}

writeByte(offset: usize, byte: u8): Wasi.errno {
if (offset >= this.length) {
return Wasi.errno.NOMEM;
}
store<u8>(this.data + offset, byte);
return Wasi.errno.SUCCESS;
}

writeBytes(offset: usize, ptr: usize, size: usize): Wasi.errno {
if (offset + size >= this.length) {
return Wasi.errno.NOMEM;
}
let dst = offset + this.data;
memory.copy(dst, ptr, size);
if (offset + size > this.size) {
this.size = offset + size;
this.writeEOT(this.size);
}
return Wasi.errno.SUCCESS;
}


stat: Wasi.filestat
}
Expand All @@ -229,7 +267,7 @@ class Directory extends File {
}

class DirectoryEntry {
constructor(public path: string, public type: Wasi.filetype) { }
constructor(public path: string, public type: Wasi.filetype, public size: usize) { }
}


Expand Down Expand Up @@ -374,20 +412,20 @@ export class FileSystem {
return res.result.read(data);
}

readString(fd: fd, offset: usize = 0): WasiResult<string> {
readString(fd: fd, max?: usize): WasiResult<string> {
let res = this.get(fd);
if (res.failed) {
return WasiResult.fail<string>(res.error);
}
return res.result.readString();
return res.result.readString(max);
}

readline(fd: fd, max?: usize): WasiResult<string> {
let res = this.get(fd);
if (res.failed) {
return WasiResult.fail<string>(res.error);
}
return res.result.readLine();
return res.result.readLine(max);
}

writeString(fd: fd, data: string, newline: boolean): Wasi.errno {
Expand Down
54 changes: 31 additions & 23 deletions packages/assemblyscript/assembly/wasa/mock/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,41 @@

const newLine: u8 = 10;

export class StringUtils {
static isNewLine(ptr: usize): boolean {
return load<u8>(ptr) == newLine;
}
static readonly NUL: u8 = 0;
static readonly EOT: u8 = 4;
static readonly LF: u8 = 10;

static fromCString(cstring: usize, max: usize = 4096): string | null {
let size: usize = 0;
while (load<u8>(cstring + size) != 0 && size < max) {
size++;
static isNewLine(ptr: usize): boolean {
return load<u8>(ptr) == this.LF;
}
if (size >= max && load<u8>(cstring + size) != 0) {
return null;

private static terminates(ptr: usize): bool {
let char: u8 = load<u8>(ptr);
return char == this.NUL || char == this.EOT
}
return String.fromUTF8(cstring, size);
}

static fromCStringTilNewLine(cstring: usize, max: usize): string | null {
let size: usize = 0;
while (load<u8>(cstring + size) != 0 && size < max) {
size++;
if (this.isNewLine(cstring + size - 1)) {
break;
}
static fromCString(cstring: usize, max: usize = 4096): string | null {
let size: usize = 0;
while (!this.terminates(cstring + size) && size < max - 1) {
size++;
}
if (size == 0) {
return null
}
return String.fromUTF8(cstring, size);
}
if (size >= max && load<u8>(cstring + size) != 0) {
return null;

static fromCStringTilNewLine(cstring: usize, max: usize): string | null {
let size: usize = 0;
while (!this.terminates(cstring + size) && size < max - 1) {
size++;
if (this.isNewLine(cstring + size - 1)) {
break;
}
}
if (size == 0) {
return null
}
return String.fromUTF8(cstring, size);
}
return String.fromUTF8(cstring, size);
}
}
7 changes: 6 additions & 1 deletion types/wasa/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ declare class FileDescriptor {
file: File | null;
fd: u32;
offset: u32;
/**
* Number of bytes written to the file.
*/
size: usize;

/**
* Write an array of bytes to a file;
Expand Down Expand Up @@ -152,7 +156,7 @@ declare class DirectoryDescriptor extends FileDescriptor {
/**
* Returns list of names of entries in the directory.
*/
listDir(): string[];
listDir(): DirectoryEntry[];

/**Path of parent directory */
parent: string;
Expand Down Expand Up @@ -342,6 +346,7 @@ declare class fs {
declare class DirectoryEntry {
path: string;
type: Wasi.filetype;
size: usize;
}

/**
Expand Down