import type { ArrayIndex, Expr, Identifier, NameRef, NumberLiteral, PropRef, ValueRef, Word, } from "./Expr.ts"; export type ParseProjectionExpression = Parse< Text, [], undefined >; type AsExpr = Extract; type Parse< Text extends string, Expressions extends Expr[], Exp extends Expr | undefined, > = Text extends `.${infer Rest}` ? Exp extends Expr ? Parse>> : never : Text extends `[:${infer Rest}` ? Parse, ValueRef<"">>> : Text extends `[${infer Rest}` ? Parse, NumberLiteral<"">>> : Text extends `]${infer Rest}` ? Parse : Text extends `]` ? Concat : Text extends `${"," | " "}${infer Rest}` ? Parse, undefined> : Text extends `#${infer Rest}` ? Parse, NameRef> : Text extends `:${infer Rest}` ? Parse, ValueRef> : Text extends `${Word}${string}` ? Text extends `${infer char}${infer Rest}` ? Parse> : never : Text extends `${Word}${string}` ? Text extends `${infer char}${infer Rest}` ? Parse> : never : Concat; type Concat< Expressions extends Expr[], CurrentExpr extends Expr | undefined, > = undefined extends CurrentExpr ? Expressions : [...Expressions, Extract]; type Append< Exp extends Expr | undefined, char extends string, > = Exp extends undefined ? Identifier : Exp extends Identifier ? Identifier<`${Name}${char}`> : Exp extends NumberLiteral ? NumberLiteral<`${Name}${char}`> : Exp extends NameRef ? NameRef<`${Name}${char}`> : Exp extends ValueRef ? ValueRef<`${Name}${char}`> : Exp extends PropRef ? PropRef, Identifier>> : Exp extends ArrayIndex ? ArrayIndex, NumberLiteral>> : never; export type ApplyProjection = Flatten< UnionToIntersection< ApplyProjectionExpr[number]> > >; type ApplyProjectionExpr = T extends undefined ? never : Exp extends PropRef ? { [p in keyof ApplyProjectionExpr]: ApplyProjectionExpr< ApplyProjectionExpr[p], i >; } : Exp extends ArrayIndex ? { [p in keyof ApplyProjectionExpr]: ApplyProjectionExpr< ApplyProjectionExpr[keyof ApplyProjectionExpr], i >; } : Exp extends Identifier ? I extends keyof T ? Pick : never : Exp extends NumberLiteral ? ParseInt extends keyof T ? Pick> : never : never; type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ( k: infer I, ) => void ? I : never; type Flatten = T extends object ? keyof T extends number ? FlattenArray>> : { [k in keyof T]: Flatten; } : T; type FlattenArray< T extends { [i in number]: any }, i extends number = 0, > = i extends keyof T ? [T[i], ...FlattenArray>] : number extends i ? [] : FlattenArray>; type BuildTuple = T["length"] extends N ? T : BuildTuple; type Inc = Extract<[...BuildTuple, any]["length"], number>; type ParseInt = N extends "0" ? 0 : N extends "1" ? 1 : N extends "2" ? 2 : N extends "3" ? 3 : N extends "4" ? 4 : N extends "5" ? 5 : N extends "6" ? 6 : N extends "7" ? 7 : N extends "8" ? 8 : N extends "9" ? 9 : number;