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