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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user