Enforce type of arg in TS DataConverter.convert (#4327)

This commit is contained in:
Eddy Ashton 2022-10-10 08:36:12 +01:00 коммит произвёл GitHub
Родитель 738ee8c569
Коммит c6f5bb55e1
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 67 добавлений и 1 удалений

Просмотреть файл

@ -32,8 +32,33 @@ export interface DataConverter<T> {
decode(arr: ArrayBuffer): T;
}
function checkBoolean(val: any) {
if (typeof val !== "boolean") {
throw new TypeError(`Value ${val} is not a boolean`);
}
}
function checkNumber(val: any) {
if (typeof val !== "number") {
throw new TypeError(`Value ${val} is not a number`);
}
}
function checkBigInt(val: any) {
if (typeof val !== "bigint") {
throw new TypeError(`Value ${val} is not a bigint`);
}
}
function checkString(val: any) {
if (typeof val !== "string") {
throw new TypeError(`Value ${val} is not a string`);
}
}
class BoolConverter implements DataConverter<boolean> {
encode(val: boolean): ArrayBuffer {
checkBoolean(val);
const buf = new ArrayBuffer(1);
new DataView(buf).setUint8(0, val ? 1 : 0);
return buf;
@ -44,6 +69,7 @@ class BoolConverter implements DataConverter<boolean> {
}
class Int8Converter implements DataConverter<number> {
encode(val: number): ArrayBuffer {
checkNumber(val);
if (val < -128 || val > 127) {
throw new RangeError("value is not within int8 range");
}
@ -57,6 +83,7 @@ class Int8Converter implements DataConverter<number> {
}
class Uint8Converter implements DataConverter<number> {
encode(val: number): ArrayBuffer {
checkNumber(val);
if (val < 0 || val > 255) {
throw new RangeError("value is not within uint8 range");
}
@ -70,6 +97,7 @@ class Uint8Converter implements DataConverter<number> {
}
class Int16Converter implements DataConverter<number> {
encode(val: number): ArrayBuffer {
checkNumber(val);
if (val < -32768 || val > 32767) {
throw new RangeError("value is not within int16 range");
}
@ -83,6 +111,7 @@ class Int16Converter implements DataConverter<number> {
}
class Uint16Converter implements DataConverter<number> {
encode(val: number): ArrayBuffer {
checkNumber(val);
if (val < 0 || val > 65535) {
throw new RangeError("value is not within uint16 range");
}
@ -96,6 +125,7 @@ class Uint16Converter implements DataConverter<number> {
}
class Int32Converter implements DataConverter<number> {
encode(val: number): ArrayBuffer {
checkNumber(val);
if (val < -2147483648 || val > 2147483647) {
throw new RangeError("value is not within int32 range");
}
@ -109,6 +139,7 @@ class Int32Converter implements DataConverter<number> {
}
class Uint32Converter implements DataConverter<number> {
encode(val: number): ArrayBuffer {
checkNumber(val);
if (val < 0 || val > 4294967295) {
throw new RangeError("value is not within uint32 range");
}
@ -122,6 +153,7 @@ class Uint32Converter implements DataConverter<number> {
}
class Int64Converter implements DataConverter<bigint> {
encode(val: bigint): ArrayBuffer {
checkBigInt(val);
const buf = new ArrayBuffer(8);
new DataView(buf).setBigInt64(0, val, true);
return buf;
@ -132,6 +164,7 @@ class Int64Converter implements DataConverter<bigint> {
}
class Uint64Converter implements DataConverter<bigint> {
encode(val: bigint): ArrayBuffer {
checkBigInt(val);
const buf = new ArrayBuffer(8);
new DataView(buf).setBigUint64(0, val, true);
return buf;
@ -142,6 +175,7 @@ class Uint64Converter implements DataConverter<bigint> {
}
class Float32Converter implements DataConverter<number> {
encode(val: number): ArrayBuffer {
checkNumber(val);
const buf = new ArrayBuffer(4);
new DataView(buf).setFloat32(0, val, true);
return buf;
@ -152,6 +186,7 @@ class Float32Converter implements DataConverter<number> {
}
class Float64Converter implements DataConverter<number> {
encode(val: number): ArrayBuffer {
checkNumber(val);
const buf = new ArrayBuffer(8);
new DataView(buf).setFloat64(0, val, true);
return buf;
@ -162,6 +197,7 @@ class Float64Converter implements DataConverter<number> {
}
class StringConverter implements DataConverter<string> {
encode(val: string): ArrayBuffer {
checkString(val);
return ccf.strToBuf(val);
}
decode(buf: ArrayBuffer): string {

Просмотреть файл

@ -17,10 +17,13 @@ describe("typedKv", function () {
const val = 65535;
it("basic", function () {
assert.isFalse(foo.has(key));
assert.isFalse(foo.has(key2));
assert.equal(foo.get(key), undefined);
foo.set(key, val);
assert.equal(foo.get(key), val);
assert.isTrue(foo.has(key));
assert.isFalse(foo.has(key2));
let found = false;
foo.forEach((v, k) => {
if (k == key && v == val) {
@ -29,7 +32,8 @@ describe("typedKv", function () {
});
assert.isTrue(found);
foo.delete(key);
assert.isNotTrue(foo.has(key));
assert.isFalse(foo.has(key));
assert.isFalse(foo.has(key2));
assert.equal(foo.get(key), undefined);
});
@ -59,3 +63,29 @@ describe("typedKv", function () {
assert.equal(foo.size, 0);
});
});
class TypeErasedKvMap<K, V> {
constructor(private map: kv.TypedKvMap<K, V>) {}
has(key: any): boolean {
return this.map.has(key);
}
get(key: any): V | undefined {
return this.map.get(key);
}
set(key: any, value: V) {
this.map.set(key, value);
}
}
describe("erased types", function () {
const bar = new TypeErasedKvMap(kv.typedKv("bar", conv.int32, conv.uint16));
const key = "baz";
const val = 65535;
it("basic", function () {
assert.throws(() => bar.has(key), `${key} is not a number`);
assert.throws(() => bar.get(key), `${key} is not a number`);
assert.throws(() => bar.set(key, val), `${key} is not a number`);
});
});