Linked map support (#801)

* able to get head

* head actually working

* Correctly get linkage

* I think it is working

* Results now return both keys and values
This commit is contained in:
Jaco Greeff
2019-03-27 15:34:11 +01:00
committed by GitHub
parent d4646f99c6
commit cda0ef3486
10 changed files with 284 additions and 70 deletions
+7 -3
View File
@@ -207,9 +207,13 @@ export class StorageFunctionType extends EnumType<PlainType | MapType> {
* @description Returns the string representation of the value
*/
toString (): string {
return this.isMap
? this.asMap.value.toString()
: this.asType.toString();
if (this.isMap) {
if (this.asMap.isLinked) {
return `(${this.asMap.value.toString()}, Linkage<${this.asMap.key.toString()}>)`;
}
return this.asMap.value.toString();
}
return this.asType.toString();
}
}
+42
View File
@@ -0,0 +1,42 @@
// Copyright 2017-2019 @polkadot/types authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Struct, Option, Tuple, Vector } from '.';
import { Constructor, Codec } from '../types';
type TypeWithValues = [Constructor, Array<any>];
export class Linkage<T extends Codec> extends Struct {
constructor (Type: Constructor, value?: any) {
super({
previous: Option.with(Type),
next: Option.with(Type)
}, value);
}
static withKey<O extends Codec> (Type: Constructor): Constructor<Linkage<O>> {
return class extends Linkage<O> {
constructor (value?: any) {
super(Type, value);
}
};
}
get previous (): Option<T> {
return this.get('previous') as Option<T>;
}
get next (): Option<T> {
return this.get('next') as Option<T>;
}
}
export class LinkageResult extends Tuple {
constructor ([TypeKey, keys]: TypeWithValues, [TypeValue, values]: TypeWithValues) {
super({
Keys: Vector.with(TypeKey),
Values: Vector.with(TypeValue)
}, [keys, values]);
}
}
+48 -37
View File
@@ -14,6 +14,7 @@ import Tuple from './Tuple';
import UInt from './UInt';
import Vector from './Vector';
import getRegistry from './typeRegistry';
import { Linkage } from './Linkage';
export enum TypeDefInfo {
Compact,
@@ -22,7 +23,8 @@ export enum TypeDefInfo {
Plain,
Struct,
Tuple,
Vector
Vector,
Linkage
}
export type TypeDef = {
@@ -130,6 +132,9 @@ export function getTypeDef (_type: Text | string, name?: string): TypeDef {
} else if (startingWith(type, 'Vec<', '>')) {
value.info = TypeDefInfo.Vector;
value.sub = getTypeDef(subType);
} else if (startingWith(type, 'Linkage<', '>')) {
value.info = TypeDefInfo.Linkage;
value.sub = getTypeDef(subType);
}
return value;
@@ -141,50 +146,56 @@ export function getTypeClass (value: TypeDef): Constructor {
if (Type) {
return Type;
}
if (value.info === TypeDefInfo.Compact) {
assert(value.sub && !Array.isArray(value.sub), 'Expected subtype for Compact');
switch (value.info) {
case TypeDefInfo.Compact:
assert(value.sub && !Array.isArray(value.sub), 'Expected subtype for Compact');
return Compact.with(
getTypeClass(value.sub as TypeDef) as Constructor<UInt>
);
} else if (value.info === TypeDefInfo.Enum) {
assert(value.sub && Array.isArray(value.sub), 'Expected subtype for Enum');
return Compact.with(
getTypeClass(value.sub as TypeDef) as Constructor<UInt>
);
case TypeDefInfo.Enum:
assert(value.sub && Array.isArray(value.sub), 'Expected subtype for Enum');
return EnumType.with(
(value.sub as Array<TypeDef>).reduce((result, sub, index) => {
result[sub.name as string] = getTypeClass(sub);
return EnumType.with(
(value.sub as Array<TypeDef>).reduce((result, sub, index) => {
result[sub.name as string] = getTypeClass(sub);
return result;
}, {} as { [index: string]: Constructor })
);
} else if (value.info === TypeDefInfo.Option) {
assert(value.sub && !Array.isArray(value.sub), 'Expected subtype for Option');
return result;
}, {} as { [index: string]: Constructor })
);
case TypeDefInfo.Option:
assert(value.sub && !Array.isArray(value.sub), 'Expected subtype for Option');
return Option.with(
getTypeClass(value.sub as TypeDef)
);
} else if (value.info === TypeDefInfo.Struct) {
assert(Array.isArray(value.sub), 'Expected nested subtypes for Struct');
return Option.with(
getTypeClass(value.sub as TypeDef)
);
case TypeDefInfo.Struct:
assert(Array.isArray(value.sub), 'Expected nested subtypes for Struct');
return Struct.with(
(value.sub as Array<TypeDef>).reduce((result, sub) => {
result[sub.name as string] = getTypeClass(sub);
return Struct.with(
(value.sub as Array<TypeDef>).reduce((result, sub) => {
result[sub.name as string] = getTypeClass(sub);
return result;
}, {} as { [index: string]: Constructor })
);
} else if (value.info === TypeDefInfo.Tuple) {
assert(Array.isArray(value.sub), 'Expected nested subtypes for Tuple');
return result;
}, {} as { [index: string]: Constructor })
);
case TypeDefInfo.Tuple:
assert(Array.isArray(value.sub), 'Expected nested subtypes for Tuple');
return Tuple.with(
(value.sub as Array<TypeDef>).map(getTypeClass)
);
} else if (value.info === TypeDefInfo.Vector) {
assert(value.sub && !Array.isArray(value.sub), 'Expected subtype for Vector');
return Tuple.with(
(value.sub as Array<TypeDef>).map(getTypeClass)
);
case TypeDefInfo.Vector:
assert(value.sub && !Array.isArray(value.sub), 'Expected subtype for Vector');
return Vector.with(
getTypeClass(value.sub as TypeDef)
);
return Vector.with(
getTypeClass(value.sub as TypeDef)
);
case TypeDefInfo.Linkage:
assert(value.sub && !Array.isArray(value.sub), 'Expected subtype for Linkage');
return Linkage.withKey(
getTypeClass(value.sub as TypeDef)
);
}
throw new Error(`Unable to determine type from '${value.type}'`);
+3 -2
View File
@@ -15,6 +15,7 @@ export interface StorageFunction {
method: string;
section: string;
toJSON: () => any;
headKey?: Uint8Array;
}
/**
@@ -38,10 +39,10 @@ export default class StorageKey extends Bytes {
if (isFunction(value)) {
return value();
} else if (Array.isArray(value)) {
const [fn, arg] = value;
const [fn, ...arg] = value;
if (isFunction(fn)) {
return fn(arg);
return fn(...arg);
}
}