as-container
Advanced tools
Comparing version 0.5.2 to 0.6.0
import { Box } from "../box"; | ||
class A { | ||
@operator("==") | ||
eq(other: this): bool { | ||
return true; | ||
} | ||
} | ||
class B extends A { | ||
b(): void { } | ||
@operator("==") | ||
eq(other: this): bool { | ||
return super.eq(other) && false; | ||
} | ||
} | ||
describe("Box", () => { | ||
@@ -8,2 +23,4 @@ it("from, new", () => { | ||
expect(box).toStrictEqual(box2); | ||
expect(new A() == new B()).toBe(true); | ||
expect(new B() == new B()).toBe(false); | ||
}); | ||
@@ -15,2 +32,3 @@ | ||
expect(b1 == b2).toBe(true); | ||
// @ts-ignore | ||
b1++; | ||
@@ -86,14 +104,26 @@ expect(b1 == b2).toBe(false); | ||
// @ts-ignore | ||
expect(box >> box2).toStrictEqual(Box.from<i64>(1)); | ||
// @ts-ignore | ||
expect(box >>> box2).toStrictEqual(Box.from<i64>(1)); | ||
// @ts-ignore | ||
expect(box << box2).toStrictEqual(Box.from<i64>(4)); | ||
// @ts-ignore | ||
expect(box & box2).toStrictEqual(Box.from<i64>(0)); | ||
// @ts-ignore | ||
expect(box | box2).toStrictEqual(Box.from<i64>(3)); | ||
// @ts-ignore | ||
expect(box ^ box2).toStrictEqual(Box.from<i64>(3)); | ||
// @ts-ignore | ||
expect(box + box2).toStrictEqual(Box.from<i64>(3)); | ||
// @ts-ignore | ||
expect(box - box2).toStrictEqual(Box.from<i64>(1)); | ||
// @ts-ignore | ||
expect(box * box2).toStrictEqual(Box.from<i64>(2)); | ||
// @ts-ignore | ||
expect(box / box2).toStrictEqual(Box.from<i64>(2)); | ||
// @ts-ignore | ||
expect(box ** box2).toStrictEqual(Box.from<i64>(2)); | ||
// @ts-ignore | ||
expect(box % box2).toStrictEqual(Box.from<i64>(0)); | ||
@@ -103,11 +133,19 @@ | ||
expect(!box3).toStrictEqual(true); | ||
// @ts-ignore | ||
expect(~box).toStrictEqual(Box.from<i64>(~2)); | ||
// @ts-ignore | ||
expect(+box4).toStrictEqual(Box.from<i64>(-1)); | ||
// @ts-ignore | ||
expect(-box4).toStrictEqual(Box.from<i64>(1)); | ||
// @ts-ignore | ||
// @ts-ignore | ||
expect(box++).toStrictEqual(Box.from<i64>(2)); | ||
expect(box).toStrictEqual(Box.from<i64>(3)); | ||
// @ts-ignore | ||
expect(++box2).toStrictEqual(Box.from<i64>(2)); | ||
// @ts-ignore | ||
expect(box3--).toStrictEqual(Box.from<i64>(0)); | ||
expect(box3).toStrictEqual(Box.from<i64>(-1)); | ||
// @ts-ignore | ||
expect(--box4).toStrictEqual(Box.from<i64>(-2)); | ||
@@ -130,14 +168,26 @@ }); | ||
// @ts-ignore | ||
expect(box >> box2).toStrictEqual(Box.from(1)); | ||
// @ts-ignore | ||
expect(box >>> box2).toStrictEqual(Box.from(1)); | ||
// @ts-ignore | ||
expect(box << box2).toStrictEqual(Box.from(4)); | ||
// @ts-ignore | ||
expect(box & box2).toStrictEqual(Box.from(0)); | ||
// @ts-ignore | ||
expect(box | box2).toStrictEqual(Box.from(3)); | ||
// @ts-ignore | ||
expect(box ^ box2).toStrictEqual(Box.from(3)); | ||
// @ts-ignore | ||
expect(box + box2).toStrictEqual(Box.from(3)); | ||
// @ts-ignore | ||
expect(box - box2).toStrictEqual(Box.from(1)); | ||
// @ts-ignore | ||
expect(box * box2).toStrictEqual(Box.from(2)); | ||
// @ts-ignore | ||
expect(box / box2).toStrictEqual(Box.from(2)); | ||
// @ts-ignore | ||
expect(box ** box2).toStrictEqual(Box.from(2)); | ||
// @ts-ignore | ||
expect(box % box2).toStrictEqual(Box.from(0)); | ||
@@ -147,11 +197,18 @@ | ||
expect(!box3).toStrictEqual(true); | ||
// @ts-ignore | ||
expect(~box).toStrictEqual(Box.from(~2)); | ||
// @ts-ignore | ||
expect(+box4).toStrictEqual(Box.from(-1)); | ||
// @ts-ignore | ||
expect(-box4).toStrictEqual(Box.from(1)); | ||
// @ts-ignore | ||
expect(box++).toStrictEqual(Box.from(2)); | ||
expect(box).toStrictEqual(Box.from(3)); | ||
// @ts-ignore | ||
expect(++box2).toStrictEqual(Box.from(2)); | ||
// @ts-ignore | ||
expect(box3--).toStrictEqual(Box.from(0)); | ||
expect(box3).toStrictEqual(Box.from(-1)); | ||
// @ts-ignore | ||
expect(--box4).toStrictEqual(Box.from(-2)); | ||
@@ -174,14 +231,27 @@ }); | ||
// @ts-ignore | ||
expect(box >> box2).toStrictEqual(Box.from<i8>(1)); | ||
// @ts-ignore | ||
expect(box >>> box2).toStrictEqual(Box.from<i8>(1)); | ||
// @ts-ignore | ||
expect(box << box2).toStrictEqual(Box.from<i8>(4)); | ||
// @ts-ignore | ||
expect(box & box2).toStrictEqual(Box.from<i8>(0)); | ||
// @ts-ignore | ||
expect(box | box2).toStrictEqual(Box.from<i8>(3)); | ||
// @ts-ignore | ||
expect(box ^ box2).toStrictEqual(Box.from<i8>(3)); | ||
// @ts-ignore | ||
expect(box + box2).toStrictEqual(Box.from<i8>(3)); | ||
// @ts-ignore | ||
expect(box - box2).toStrictEqual(Box.from<i8>(1)); | ||
// @ts-ignore | ||
expect(box * box2).toStrictEqual(Box.from<i8>(2)); | ||
// @ts-ignore | ||
expect(box / box2).toStrictEqual(Box.from<i8>(2)); | ||
// @ts-ignore | ||
// @ts-ignore | ||
expect(box ** box2).toStrictEqual(Box.from<i8>(2)); | ||
// @ts-ignore | ||
expect(box % box2).toStrictEqual(Box.from<i8>(0)); | ||
@@ -191,11 +261,19 @@ | ||
expect(!box3).toStrictEqual(true); | ||
// @ts-ignore | ||
expect(~box).toStrictEqual(Box.from<i8>(~2)); | ||
// @ts-ignore | ||
expect(+box4).toStrictEqual(Box.from<i8>(-1)); | ||
// @ts-ignore | ||
expect(-box4).toStrictEqual(Box.from<i8>(1)); | ||
// @ts-ignore | ||
expect(box++).toStrictEqual(Box.from<i8>(2)); | ||
expect(box).toStrictEqual(Box.from<i8>(3)); | ||
// @ts-ignore | ||
expect(++box2).toStrictEqual(Box.from<i8>(2)); | ||
// @ts-ignore | ||
expect(box3--).toStrictEqual(Box.from<i8>(0)); | ||
// @ts-ignore | ||
expect(box3).toStrictEqual(Box.from<i8>(-1)); | ||
// @ts-ignore | ||
expect(--box4).toStrictEqual(Box.from<i8>(-2)); | ||
@@ -217,14 +295,26 @@ }); | ||
// @ts-ignore | ||
expect(box >> box2).toStrictEqual(Box.from<u8>(1)); | ||
// @ts-ignore | ||
expect(box >>> box2).toStrictEqual(Box.from<u8>(1)); | ||
// @ts-ignore | ||
expect(box << box2).toStrictEqual(Box.from<u8>(4)); | ||
// @ts-ignore | ||
expect(box & box2).toStrictEqual(Box.from<u8>(0)); | ||
// @ts-ignore | ||
expect(box | box2).toStrictEqual(Box.from<u8>(3)); | ||
// @ts-ignore | ||
expect(box ^ box2).toStrictEqual(Box.from<u8>(3)); | ||
// @ts-ignore | ||
expect(box + box2).toStrictEqual(Box.from<u8>(3)); | ||
// @ts-ignore | ||
expect(box - box2).toStrictEqual(Box.from<u8>(1)); | ||
// @ts-ignore | ||
expect(box * box2).toStrictEqual(Box.from<u8>(2)); | ||
// @ts-ignore | ||
expect(box / box2).toStrictEqual(Box.from<u8>(2)); | ||
// @ts-ignore | ||
expect(box ** box2).toStrictEqual(Box.from<u8>(2)); | ||
// @ts-ignore | ||
expect(box % box2).toStrictEqual(Box.from<u8>(0)); | ||
@@ -234,7 +324,11 @@ | ||
expect(!box3).toStrictEqual(true); | ||
// @ts-ignore | ||
expect(~box).toStrictEqual(Box.from<u8>(~2)); | ||
// @ts-ignore | ||
expect(box++).toStrictEqual(Box.from<u8>(2)); | ||
expect(box).toStrictEqual(Box.from<u8>(3)); | ||
// @ts-ignore | ||
expect(++box2).toStrictEqual(Box.from<u8>(2)); | ||
// @ts-ignore | ||
expect(box3--).toStrictEqual(Box.from<u8>(0)); | ||
@@ -256,2 +350,3 @@ expect(box3).toStrictEqual(Box.from<u8>(255)); | ||
// @ts-ignore | ||
expect(box + box2).toStrictEqual(Box.from("21")); | ||
@@ -261,2 +356,2 @@ }); | ||
class Person {} | ||
class Person { } |
@@ -10,4 +10,5 @@ import { Result } from "../../primitive/result"; | ||
it("offsetof", () => { | ||
expect(offsetof<Result<i32, i8>>()).toBe(8); | ||
expect(offsetof<Result<string, u64>>()).toBe(8); | ||
expect(offsetof<Result<i32, i8>>()).toBe(6); | ||
expect(offsetof<Result<string, u64>>()).toBe(17); | ||
expect(offsetof<Result<string, u32>>()).toBe(9); | ||
}); | ||
@@ -125,5 +126,3 @@ | ||
expect( | ||
x | ||
.andThen<string>((s) => Result.Ok<string, string>(s + s)) | ||
.unwrap() | ||
x.andThen<string>((s) => Result.Ok<string, string>(s + s)).unwrap() | ||
).toBe("okok"); | ||
@@ -130,0 +129,0 @@ |
import { MapFn, RecoveryFn } from "../shared"; | ||
import { Optionable } from "../optionable"; | ||
import { Box } from "../box"; | ||
import { instantiateZero } from "../util"; | ||
@@ -11,7 +11,9 @@ export type FlatMapFn<T, U> = MapFn<T, Option<U>>; | ||
* | ||
* The Option version can wrap the primitive and reference type, but it will take up some more bytes and increase reference overhead. | ||
* The Option version can wrap both the primitive and reference type, but it will take up some more bytes and increase overhead. | ||
*/ | ||
export class Option<T> implements Optionable<T> { | ||
// @ts-ignore | ||
@unsafe | ||
constructor( | ||
protected readonly _val: Box<T> | null = null, | ||
protected readonly _val: T = instantiateZero<T>(), | ||
protected _isNone: bool = true | ||
@@ -22,3 +24,3 @@ ) {} | ||
static Some<T>(val: T): Option<T> { | ||
return new Option<T>(Box.from(val), false); | ||
return new Option<T>(val, false); | ||
} | ||
@@ -54,3 +56,3 @@ | ||
assert(this.isSome, msg); | ||
return this._val!.unwrap(); | ||
return this._val; | ||
} | ||
@@ -61,3 +63,3 @@ | ||
if (this.isSome) { | ||
return this._val!.unwrap(); | ||
return this._val; | ||
} | ||
@@ -70,3 +72,3 @@ return def; | ||
if (this.isSome) { | ||
return this._val!.unwrap(); | ||
return this._val; | ||
} | ||
@@ -80,3 +82,3 @@ return fn(); | ||
} | ||
return Option.Some(fn(this._val!.unwrap())); | ||
return Option.Some(fn(this._val)); | ||
} | ||
@@ -88,3 +90,3 @@ | ||
} | ||
return fn(this._val!.unwrap()); | ||
return fn(this._val); | ||
} | ||
@@ -96,3 +98,3 @@ | ||
} | ||
return fn(this._val!.unwrap()); | ||
return fn(this._val); | ||
} | ||
@@ -104,3 +106,3 @@ | ||
} | ||
return fn(this._val!.unwrap()) as Option<U>; | ||
return fn(this._val) as Option<U>; | ||
} | ||
@@ -122,3 +124,3 @@ | ||
if (this.isSome) { | ||
return Option.Some<T>(this._val!.unwrap()); | ||
return Option.Some<T>(this._val); | ||
} | ||
@@ -130,3 +132,3 @@ return def; | ||
if (this.isSome) { | ||
return Option.Some<T>(this._val!.unwrap()); | ||
return Option.Some<T>(this._val); | ||
} | ||
@@ -142,3 +144,3 @@ return defFn(); | ||
} else if (this.isSome && other.isSome) { | ||
return this._val!.unwrap() == other._val!.unwrap(); | ||
return this._val == other._val; | ||
} else { | ||
@@ -145,0 +147,0 @@ return false; |
import { Option } from "./option"; | ||
import { MapFn, RecoveryWithErrorFn } from "../shared"; | ||
import { Resultable } from "../resultable"; | ||
import { Box } from "../box"; | ||
import { instantiateZero } from "../util"; | ||
@@ -14,13 +14,24 @@ export type FlatMapOkFn<O, U, E> = MapFn<O, Result<U, E>>; | ||
* | ||
* The Result version can wrap the primitive and reference type, but it will increase reference overhead | ||
* The Result version can both wrap the primitive and reference type, but it will increase reference overhead | ||
*/ | ||
export class Result<O, E> implements Resultable<O, E> { | ||
protected readonly _ok: O; | ||
protected readonly _err: E; | ||
// Note: make _isOk in the last is good for layout when err size is less than ok size. | ||
protected readonly _isOk: bool; | ||
// @ts-ignore | ||
@unsafe | ||
private constructor( | ||
protected readonly _ok: Box<O> | null, | ||
protected readonly _err: Box<E> | null | ||
) {} | ||
isOk: bool, | ||
ok: O = instantiateZero<O>(), | ||
err: E = instantiateZero<E>() | ||
) { | ||
this._isOk = isOk; | ||
this._ok = ok; | ||
this._err = err; | ||
} | ||
@inline | ||
static Ok<O, E>(ok: O): Result<O, E> { | ||
return new Result<O, E>(Box.from<O>(ok), null); | ||
return new Result<O, E>(true, ok); | ||
} | ||
@@ -30,3 +41,3 @@ | ||
static Err<O, E>(err: E): Result<O, E> { | ||
return new Result<O, E>(null, Box.from<E>(err)); | ||
return new Result<O, E>(false, instantiateZero<O>(), err); | ||
} | ||
@@ -36,3 +47,3 @@ | ||
get isOk(): bool { | ||
return this._err === null; | ||
return this._isOk; | ||
} | ||
@@ -42,3 +53,3 @@ | ||
get isErr(): bool { | ||
return this._ok === null; | ||
return !this._isOk; | ||
} | ||
@@ -48,3 +59,3 @@ | ||
clone(): this { | ||
return instantiate<this>(this._ok, this._err); | ||
return instantiate<this>(this._isOk, this._ok, this._err); | ||
} | ||
@@ -155,3 +166,3 @@ | ||
assert(this.isOk, message); | ||
return this._ok!.unwrap() as O; | ||
return this._ok; | ||
} | ||
@@ -162,3 +173,3 @@ | ||
assert(this.isErr, message); | ||
return this._err!.unwrap() as E; | ||
return this._err; | ||
} | ||
@@ -165,0 +176,0 @@ |
@@ -0,14 +1,18 @@ | ||
// @ts-ignore | ||
@inline | ||
@unsafe | ||
export function instantiateZero<T>(): T { | ||
let t: T; | ||
if (isFloat(t)) { | ||
if (isFloat<T>()) { | ||
// @ts-ignore | ||
return 0; | ||
} else if (isInteger(t)) { | ||
} else if (isInteger<T>()) { | ||
// @ts-ignore | ||
return 0; | ||
} else if (isBoolean(t)) { | ||
} else if (isBoolean<T>()) { | ||
// @ts-ignore | ||
return false; | ||
} else if (isNullable(t)) { | ||
return null; | ||
} else if (isReference<T>()) { | ||
return changetype<T>(0); | ||
} | ||
return instantiate<T>(); | ||
} |
@@ -0,1 +1,15 @@ | ||
## 0.6.0 (2021-07-30) | ||
* feat(primitive): improve result/option layout (#35) ([1844637](https://github.com/yjhmelody/as-container/commit/1844637)), closes [#35](https://github.com/yjhmelody/as-container/issues/35) | ||
* chore(deps-dev): bump @typescript-eslint/eslint-plugin (#28) ([23f0c62](https://github.com/yjhmelody/as-container/commit/23f0c62)), closes [#28](https://github.com/yjhmelody/as-container/issues/28) | ||
* chore(deps-dev): bump @typescript-eslint/eslint-plugin (#33) ([7032070](https://github.com/yjhmelody/as-container/commit/7032070)), closes [#33](https://github.com/yjhmelody/as-container/issues/33) | ||
* chore(deps-dev): bump @typescript-eslint/parser from 4.22.1 to 4.26.0 (#27) ([c9cfcba](https://github.com/yjhmelody/as-container/commit/c9cfcba)), closes [#27](https://github.com/yjhmelody/as-container/issues/27) | ||
* chore(deps-dev): bump @typescript-eslint/parser from 4.26.1 to 4.28.1 (#34) ([e4e1559](https://github.com/yjhmelody/as-container/commit/e4e1559)), closes [#34](https://github.com/yjhmelody/as-container/issues/34) | ||
* chore(deps-dev): bump assemblyscript from 0.18.32 to 0.19.5 (#31) ([0f796f0](https://github.com/yjhmelody/as-container/commit/0f796f0)), closes [#31](https://github.com/yjhmelody/as-container/issues/31) | ||
* chore(deps-dev): bump eslint from 7.25.0 to 7.27.0 (#30) ([625a0ed](https://github.com/yjhmelody/as-container/commit/625a0ed)), closes [#30](https://github.com/yjhmelody/as-container/issues/30) | ||
* chore(deps-dev): bump eslint from 7.27.0 to 7.29.0 (#32) ([05c4b38](https://github.com/yjhmelody/as-container/commit/05c4b38)), closes [#32](https://github.com/yjhmelody/as-container/issues/32) | ||
* chore(deps-dev): bump typescript from 4.2.4 to 4.3.2 (#29) ([e9228d6](https://github.com/yjhmelody/as-container/commit/e9228d6)), closes [#29](https://github.com/yjhmelody/as-container/issues/29) | ||
## <small>0.5.2 (2021-05-08)</small> | ||
@@ -2,0 +16,0 @@ |
{ | ||
"name": "as-container", | ||
"version": "0.5.2", | ||
"version": "0.6.0", | ||
"description": "assemblyscript version of Rust Option<T> and Result<T, E> and Box<T> etc.", | ||
@@ -29,10 +29,8 @@ "author": "yjhmelody <yjh465402634@gmail.com>", | ||
"devDependencies": { | ||
"@as-pect/assembly": "^6.1", | ||
"@as-pect/cli": "^6.1", | ||
"@as-pect/core": "^6.1", | ||
"@typescript-eslint/eslint-plugin": "4.22", | ||
"@typescript-eslint/parser": "4.22", | ||
"assemblyscript": "^0.18", | ||
"eslint": "7.25", | ||
"typescript": "4.2" | ||
"@as-pect/cli": "^6.2", | ||
"@typescript-eslint/eslint-plugin": "^4.28", | ||
"@typescript-eslint/parser": "^4.28", | ||
"assemblyscript": "^0.19.9", | ||
"eslint": "^7.28", | ||
"typescript": "^4.3" | ||
}, | ||
@@ -39,0 +37,0 @@ "files": [ |
@@ -9,2 +9,4 @@ # as-container | ||
## APIs | ||
### Box | ||
@@ -57,4 +59,4 @@ | ||
The default version can handle any type including primitive type. But because the basic types need to be encapsulated by reference types, the reference type itself has a layer of reference overhead. | ||
The default version can handle any type including primitive type. But because the primitive types need one more byte to record state, it may take more overhead. | ||
If you always use reference types as Option/Result parameters and need better performance, then you can use the type with the same name under `as-container/reference`. |
84296
6
29
2039
61