// Copyright 2017-2021 @axiasolar/types authors & contributors // SPDX-License-Identifier: Apache-2.0 import type { BTreeMap, BTreeSet, CodecSet, Compact, Enum, HashMap, Linkage, Option, Range, RangeInclusive, Result, Struct, U8aFixed, Vec, VecFixed } from '../codec'; import type { Bytes, Null, u8 } from '../primitive'; import type { Codec, Constructor } from './codec'; import type { ICompact, IEnum, IMap, IMethod, INumber, IOption, IResult, ISet, IStruct, ITuple, IU8a, IVec } from './interfaces'; import type { InterfaceTypes } from './registry'; export type DetectCodec = // This is weird - it looks the wrong way around (i.e. T check should be done first), however // it does work (as evident with checkTypes) and is problematic the other way around K extends keyof InterfaceTypes ? InterfaceTypes[K] : T extends ICompact | IEnum | IMap | IMethod | INumber | IOption | IResult | ISet | IStruct | ITuple | IU8a | IVec ? T : __Codec<__Codecs<__Tokenize<__Sanitize>[0]>>; export type DetectConstructor = Constructor>; export type __Codec = V[0] extends Codec ? V[0] : Codec; // trim leading and trailing spaces and unused portions, e.g `...;]` export type __Sanitize = K extends ` ${infer X}` | `${infer X} ` | ` ${infer X} ` ? __Sanitize : K extends `${infer A} ${infer B}` ? __Sanitize<`${A}${B}`> : K extends `${infer A};${string}]${infer B}` ? __Sanitize<`${A}${B}`> : K extends `${infer X};${string}]` ? __Sanitize : K; export type __Value = string | Record | __Value[]; export type __MapWrapOne = { 'BTreeSet<': BTreeSet; 'Compact<': C extends INumber ? Compact : Codec; 'Linkage<': Linkage; 'Option<': Option; 'Range<': C extends INumber ? Range : Codec; 'RangeInclusive<': C extends INumber ? RangeInclusive : Codec; 'Vec<': C extends u8 ? Bytes : Vec; '[': C extends u8 ? U8aFixed : VecFixed; }; // FIXME We don't cater for Int< & UInt< here. These could be problematic, since it has // a variable number of inner arguments, better would be to just strip them inside the sanitize export type __MapWrapTwo = { 'BTreeMap<': BTreeMap; 'HashMap<': HashMap; 'Result<': Result; }; export type __WrapOne = keyof __MapWrapOne; export type __WrapTwo = keyof __MapWrapTwo; export type __Wrap = __WrapOne | __WrapTwo; export type __ToStruct> = K['_enum'] extends true ? Enum : K['_set'] extends true ? CodecSet : Struct; export type __ToTuple = O[0] extends Codec ? O[1] extends Codec ? ITuple : O[0] : Null; export type __CodecFirst = K extends keyof InterfaceTypes ? InterfaceTypes[K] : K extends unknown[] ? __ToTuple<__Codecs> : K extends Record ? __ToStruct : Codec; export type __CodecsNext = K extends __WrapOne ? C extends [Codec, ...infer X] ? [__MapWrapOne[K], ...X] : Codec : K extends __WrapTwo ? C extends [Codec, Codec, ...infer X] ? [__MapWrapTwo[K], ...X] : Codec : [__CodecFirst, ...C]; export type __Codecs = T extends [infer K, ...infer N] ? __CodecsNext> : []; export type __Combine = I extends '' ? V : [...V, I]; export type __CombineInner = I extends '' ? [...V, X] : [I, ...V, X]; // FIXME At this point enum/set/struct are empty, no field indicators, just type indicators export type __TokenizeStruct = __Tokenize>; export type __TokenizeTuple = __Tokenize>; export type __TokenizeWrapped = K extends `${infer X}${R}` ? X extends '[' ? __Tokenize, '[']> : __Tokenize> : never; export type __TokenizeKnown = K extends `${infer X}${',' | '>'}${R}` ? __Tokenize> : never; // NOTE For recursion limits, it is more optimal to use __Sanitize with conjunction with __Tokenize // below, even while we do more matching (Number of characters iterated through is the most problematic) export type __Tokenize = K extends '' | '>' | ')' | '}' ? [__Combine, ''] : K extends `${__Wrap}${infer R}` ? __TokenizeWrapped : K extends `${',' | '>'}${infer R}` ? __Tokenize> : K extends `${')' | '}'}${infer R}` ? [__Combine, R] : K extends `(${infer R}` ? __TokenizeTuple<__Tokenize, V, I> : K extends `{${infer R}` ? __TokenizeStruct<__Tokenize, V, I, R> : K extends `${keyof InterfaceTypes}${',' | '>'}${infer R}` ? __TokenizeKnown : K extends `${infer C}${infer R}` ? __Tokenize : [__Combine, ''];