Fix struct keys, log additional decoding error info (#872)

* Re-create test cases for failures

* Fix cloberring of keys

* Add logging to pinpoint decoding failures
This commit is contained in:
Jaco Greeff
2019-05-27 15:46:30 +12:00
committed by ian.he
parent f3f1807013
commit 486412d051
5 changed files with 138 additions and 58 deletions
+30 -18
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { hexToU8a, isHex, isObject, isU8a, u8aConcat, u8aToHex } from '@plugnet/util';
import { hexToU8a, isHex, isObject, isU8a, isUndefined, u8aConcat, u8aToHex } from '@plugnet/util';
import { Codec, Constructor, ConstructorDef } from '../types';
import { compareMap, decodeU8a } from './utils';
@@ -79,6 +79,7 @@ export default class Struct<
return Object.keys(Types).reduce((raw: T, key: keyof S, index) => {
// TS2322: Type 'Codec' is not assignable to type 'T[keyof S]'.
(raw as any)[key] = values[index];
return raw;
}, {} as T);
} else if (!value) {
@@ -99,23 +100,29 @@ export default class Struct<
// Types, result or any other maps, it's camelCase
const jsonKey = (jsonMap.get(key as any) && !value[key]) ? jsonMap.get(key as any) : key;
if (Array.isArray(value)) {
raw[key] = value[index] instanceof Types[key]
? value[index]
: new Types[key](value[index]);
} else if (value instanceof Map) {
const mapped = value.get(jsonKey);
try {
if (Array.isArray(value)) {
raw[key] = value[index] instanceof Types[key]
? value[index]
: new Types[key](value[index]);
} else if (value instanceof Map) {
const mapped = value.get(jsonKey);
// TS2322: Type 'Codec' is not assignable to type 'T[keyof S]'.
(raw as any)[key] = mapped instanceof Types[key]
? mapped
: new Types[key](mapped);
} else if (isObject(value)) {
raw[key] = value[jsonKey as string] instanceof Types[key]
? value[jsonKey as string]
: new Types[key](value[jsonKey as string]);
} else {
throw new Error(`Struct: cannot decode type ${Types[key].name} with value ${JSON.stringify(value)}`);
// TS2322: Type 'Codec' is not assignable to type 'T[keyof S]'.
(raw as any)[key] = mapped instanceof Types[key]
? mapped
: new Types[key](mapped);
} else if (isObject(value)) {
raw[key] = value[jsonKey as string] instanceof Types[key]
? value[jsonKey as string]
: new Types[key](value[jsonKey as string]);
} else {
throw new Error(`Struct: cannot decode type ${Types[key].name} with value ${JSON.stringify(value)}`);
}
} catch (error) {
console.error(`Unable to decode Struct on key '${jsonKey}': ${error.message}`);
throw error;
}
return raw;
@@ -130,6 +137,11 @@ export default class Struct<
super(Types, value, jsonMap);
(Object.keys(Types) as Array<keyof S>).forEach((key) => {
// do not clobber existing properties on the object
if (!isUndefined((this as any)[key])) {
return;
}
Object.defineProperty(this, key, {
enumerable: true,
get: () => this.get(key)
@@ -212,8 +224,8 @@ export default class Struct<
toJSON (): any {
return [...this.keys()].reduce((json, key) => {
const jsonKey = this._jsonMap.get(key) || key;
const value = this.get(key);
json[jsonKey] = value && value.toJSON();
return json;
+7 -1
View File
@@ -41,7 +41,13 @@ export default class Tuple extends AbstractArray<Codec> {
: Object.values(_Types);
return Types.map((Type, index) => {
return new Type(value && value[index]);
try {
return new Type(value && value[index]);
} catch (error) {
console.error(`Unable to decode Tuple on index ${index}`, error.message);
throw error;
}
});
}
+11 -5
View File
@@ -29,11 +29,17 @@ export default class Vector<T extends Codec> extends AbstractArray<T> {
static decodeVector<T extends Codec> (Type: Constructor<T>, value: Vector<any> | Uint8Array | string | Array<any>): Array<T> {
if (Array.isArray(value)) {
return value.map((entry) =>
entry instanceof Type
? entry
: new Type(entry)
);
return value.map((entry, index) => {
try {
return entry instanceof Type
? entry
: new Type(entry);
} catch (error) {
console.error(`Unable to decode Vector on index ${index}`, error.message);
throw error;
}
});
}
const u8a = u8aToU8a(value);
+9 -2
View File
@@ -21,7 +21,14 @@ export default function decodeU8a (u8a: Uint8Array, _types: Constructor[] | { [i
}
const Type = types[0];
const value = new Type(u8a);
return [value].concat(decodeU8a(u8a.subarray(value.encodedLength), types.slice(1)));
try {
const value = new Type(u8a);
return [value].concat(decodeU8a(u8a.subarray(value.encodedLength), types.slice(1)));
} catch (error) {
console.error(`Unable to decode Uint8Array for type '${Type.name}': ${error.message}`);
throw error;
}
}