Adjustments for getTypeDef (#4944)
* Adjustments for getTypeDef * Cleanup unneeded + * Adjust sanitize replacers * Ordering * Adjust sanitize
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
|
||||
import type { Registry } from '@polkadot/types/types';
|
||||
import type { AnyString, Registry } from '@polkadot/types/types';
|
||||
import type { TypeDef } from '@polkadot/types-create/types';
|
||||
|
||||
import Handlebars from 'handlebars';
|
||||
@@ -270,7 +270,7 @@ const formatters: Record<TypeDefInfo, (registry: Registry, typeDef: TypeDef, def
|
||||
*/
|
||||
/** @internal */
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export function formatType (registry: Registry, definitions: Record<string, ModuleTypes>, type: string | String | TypeDef, imports: TypeImports, withShortcut = false): string {
|
||||
export function formatType (registry: Registry, definitions: Record<string, ModuleTypes>, type: AnyString | TypeDef, imports: TypeImports, withShortcut = false): string {
|
||||
let typeDef: TypeDef;
|
||||
|
||||
if (isString(type)) {
|
||||
|
||||
@@ -53,10 +53,6 @@ describe('sanitize', (): void => {
|
||||
it('removes on embedded values (all)', (): void => {
|
||||
expect(fn('(T::AccountId, slashing::SpanIndex)')).toEqual('(AccountId, SpanIndex)');
|
||||
});
|
||||
|
||||
it('keeps with allowNamespaces', (): void => {
|
||||
expect(fn('::slashing::SpanIndex', { allowNamespaces: true })).toEqual('slashing::SpanIndex');
|
||||
});
|
||||
});
|
||||
|
||||
describe('bounded', (): void => {
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
// Copyright 2017-2022 @polkadot/types-codec authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
interface SanitizeOptions {
|
||||
allowNamespaces?: boolean;
|
||||
}
|
||||
import { AnyString } from '../types';
|
||||
|
||||
type Mapper = (value: string, options?: SanitizeOptions) => string;
|
||||
type Mapper = (value: string) => string;
|
||||
|
||||
const BOUNDED = ['BTreeMap', 'BTreeSet', 'HashMap', 'Vec'];
|
||||
const ALLOWED_BOXES = BOUNDED.concat(['Compact', 'DoNotConstruct', 'Int', 'Linkage', 'Range', 'RangeInclusive', 'Result', 'Option', 'UInt', 'WrapperKeepOpaque', 'WrapperOpaque']);
|
||||
@@ -165,7 +163,7 @@ export function removeExtensions (type: string, isSized: boolean): Mapper {
|
||||
}
|
||||
|
||||
export function removeColons (): Mapper {
|
||||
return (value: string, { allowNamespaces }: SanitizeOptions = {}): string => {
|
||||
return (value: string): string => {
|
||||
let index = 0;
|
||||
|
||||
while (index !== -1) {
|
||||
@@ -174,10 +172,6 @@ export function removeColons (): Mapper {
|
||||
if (index === 0) {
|
||||
value = value.substring(2);
|
||||
} else if (index !== -1) {
|
||||
if (allowNamespaces) {
|
||||
return value;
|
||||
}
|
||||
|
||||
let start = index;
|
||||
|
||||
while (start !== -1 && !BOX_PRECEDING.includes(value[start])) {
|
||||
@@ -203,7 +197,7 @@ export function removeGenerics (): Mapper {
|
||||
return (
|
||||
(
|
||||
start >= 0 &&
|
||||
value.substring(start, start + box.length) === box
|
||||
value.substring(start, index) === box
|
||||
) && (
|
||||
// make sure it is stand-alone, i.e. don't catch ElectionResult<...> as Result<...>
|
||||
start === 0 ||
|
||||
@@ -225,15 +219,12 @@ export function removeGenerics (): Mapper {
|
||||
};
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
function pairOfReplacer (v: string): string {
|
||||
return `(${v},${v})`;
|
||||
}
|
||||
|
||||
// remove the PairOf wrappers
|
||||
export function removePairOf (): Mapper {
|
||||
const replacer = (v: string) => `(${v},${v})`;
|
||||
|
||||
return (value: string) =>
|
||||
replaceTagWith(value, 'PairOf<', pairOfReplacer);
|
||||
replaceTagWith(value, 'PairOf<', replacer);
|
||||
}
|
||||
|
||||
// remove the type traits
|
||||
@@ -269,39 +260,31 @@ export function removeTraits (): Mapper {
|
||||
};
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
function wrapReplacer (v: string): string {
|
||||
return v;
|
||||
}
|
||||
|
||||
// remove wrapping values, i.e. Box<Proposal> -> Proposal
|
||||
export function removeWrap (check: string): Mapper {
|
||||
const replacer = (v: string) => v;
|
||||
|
||||
return (value: string) =>
|
||||
replaceTagWith(value, check, wrapReplacer);
|
||||
replaceTagWith(value, check, replacer);
|
||||
}
|
||||
|
||||
const sanitizeMap = new Map<string, string>();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export function sanitize (value: String | string, options?: SanitizeOptions): string {
|
||||
export function sanitize (value: AnyString): string {
|
||||
const startValue = value.toString();
|
||||
const memoized = sanitizeMap.get(startValue);
|
||||
|
||||
if (memoized) {
|
||||
return memoized;
|
||||
}
|
||||
|
||||
let result = startValue;
|
||||
|
||||
if (!options) {
|
||||
const memoized = sanitizeMap.get(startValue);
|
||||
|
||||
if (memoized) {
|
||||
return memoized;
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < mappings.length; i++) {
|
||||
result = mappings[i](result, options);
|
||||
result = mappings[i](result);
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
sanitizeMap.set(startValue, result);
|
||||
}
|
||||
sanitizeMap.set(startValue, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2017-2022 @polkadot/types-create authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { AnyString } from '@polkadot/types-codec/types';
|
||||
import type { TypeDef } from '@polkadot/types-create/types';
|
||||
|
||||
import { sanitize } from '@polkadot/types-codec';
|
||||
@@ -15,6 +16,8 @@ interface TypeDefOptions {
|
||||
}
|
||||
|
||||
const MAX_NESTED = 64;
|
||||
const MAX_FIX_LEN = 2048;
|
||||
const MAX_BIT_LEN = 8192;
|
||||
const KNOWN_INTERNALS = ['_alias', '_fallback'];
|
||||
|
||||
function getTypeString (typeOrObj: any): string {
|
||||
@@ -132,8 +135,7 @@ function _decodeFixedVec (value: TypeDef, type: string, _: string, count: number
|
||||
const [strLength, displayName] = type.substring(index + 1, max).split(';');
|
||||
const length = parseInt(strLength.trim(), 10);
|
||||
|
||||
// as a first round, only u8 via u8aFixed, we can add more support
|
||||
assert(length <= 256, () => `${type}: Only support for [Type; <length>], where length <= 256`);
|
||||
assert(length <= MAX_FIX_LEN, () => `${type}: Only support for [Type; <length>], where length <= ${MAX_FIX_LEN}`);
|
||||
|
||||
value.displayName = displayName;
|
||||
value.length = length;
|
||||
@@ -157,8 +159,7 @@ function _decodeAnyInt (value: TypeDef, type: string, _: string, clazz: 'Int' |
|
||||
const [strLength, displayName] = type.substring(clazz.length + 1, type.length - 1).split(',');
|
||||
const length = parseInt(strLength.trim(), 10);
|
||||
|
||||
// as a first round, only u8 via u8aFixed, we can add more support
|
||||
assert(length <= 8192 && (length % 8) === 0, () => `${type}: Only support for ${clazz}<bitLength>, where length <= 8192 and a power of 8, found ${length}`);
|
||||
assert(length <= MAX_BIT_LEN && (length % 8) === 0, () => `${type}: Only support for ${clazz}<bitLength>, where length <= ${MAX_BIT_LEN} and a power of 8, found ${length}`);
|
||||
|
||||
value.displayName = displayName;
|
||||
value.length = length;
|
||||
@@ -216,8 +217,7 @@ function extractSubType (type: string, [start, end]: [string, string, TypeDefInf
|
||||
return type.substring(start.length, type.length - end.length);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export function getTypeDef (_type: String | string, { displayName, name }: TypeDefOptions = {}, count = 0): TypeDef {
|
||||
export function getTypeDef (_type: AnyString, { displayName, name }: TypeDefOptions = {}, count = 0): TypeDef {
|
||||
// create the type via Type, allowing types to be sanitized
|
||||
const type = sanitize(_type);
|
||||
const value: TypeDef = { displayName, info: TypeDefInfo.Plain, name, type };
|
||||
|
||||
@@ -36,13 +36,13 @@ describe('typeSplit', (): void => {
|
||||
|
||||
it('checks for unclosed vec', (): void => {
|
||||
expect(
|
||||
(): string[] => typeSplit('Text, Vec<u64')
|
||||
() => typeSplit('Text, Vec<u64')
|
||||
).toThrow(/Invalid definition/);
|
||||
});
|
||||
|
||||
it('checks for unclosed tuple', (): void => {
|
||||
expect(
|
||||
(): string[] => typeSplit('Text, (u64, u32')
|
||||
() => typeSplit('Text, (u64, u32')
|
||||
).toThrow(/Invalid definition/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,46 +3,51 @@
|
||||
|
||||
import { assert } from '@polkadot/util';
|
||||
|
||||
function isNotNested (...counters: number[]): boolean {
|
||||
return !counters.some((counter): boolean => counter !== 0);
|
||||
}
|
||||
|
||||
// safely split a string on ', ' while taking care of any nested occurences
|
||||
export function typeSplit (type: string): string[] {
|
||||
let [cDepth, fDepth, sDepth, tDepth, start] = [0, 0, 0, 0, 0];
|
||||
const result = [];
|
||||
const result: string[] = [];
|
||||
|
||||
const extract = (index: number): void => {
|
||||
if (isNotNested(cDepth, fDepth, sDepth, tDepth)) {
|
||||
result.push(type.substring(start, index).trim());
|
||||
start = index + 1;
|
||||
}
|
||||
};
|
||||
// these are the depths of the various tokens: <, [, {, (
|
||||
let c = 0;
|
||||
let f = 0;
|
||||
let s = 0;
|
||||
let t = 0;
|
||||
|
||||
for (let index = 0; index < type.length; index++) {
|
||||
switch (type[index]) {
|
||||
// current start position
|
||||
let start = 0;
|
||||
|
||||
for (let i = 0; i < type.length; i++) {
|
||||
switch (type[i]) {
|
||||
// if we are not nested, add the type
|
||||
case ',': extract(index); break;
|
||||
case ',': {
|
||||
if (!(c || f || s || t)) {
|
||||
result.push(type.substring(start, i).trim());
|
||||
start = i + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// adjust compact/vec (and friends) depth
|
||||
case '<': cDepth++; break;
|
||||
case '>': cDepth--; break;
|
||||
case '<': c++; break;
|
||||
case '>': c--; break;
|
||||
|
||||
// adjust fixed vec depths
|
||||
case '[': fDepth++; break;
|
||||
case ']': fDepth--; break;
|
||||
case '[': f++; break;
|
||||
case ']': f--; break;
|
||||
|
||||
// adjust struct depth
|
||||
case '{': sDepth++; break;
|
||||
case '}': sDepth--; break;
|
||||
case '{': s++; break;
|
||||
case '}': s--; break;
|
||||
|
||||
// adjust tuple depth
|
||||
case '(': tDepth++; break;
|
||||
case ')': tDepth--; break;
|
||||
case '(': t++; break;
|
||||
case ')': t--; break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(isNotNested(cDepth, fDepth, sDepth, tDepth), () => `Invalid definition (missing terminators) found in ${type}`);
|
||||
// ensure we have all the terminators taken care of
|
||||
assert(!(c || f || s || t), () => `Invalid definition (missing terminators) found in ${type}`);
|
||||
|
||||
// the final leg of the journey
|
||||
result.push(type.substring(start, type.length).trim());
|
||||
|
||||
Reference in New Issue
Block a user