refactor(struct): reorder generic parameters

This commit is contained in:
Simon Chan 2020-09-25 14:45:12 +08:00
parent 3ef62d41d6
commit 544cc8d0e4
2 changed files with 59 additions and 43 deletions

View file

@ -204,7 +204,10 @@ export class AdbSync extends AutoDisposable {
this.stream.close(); this.stream.close();
} }
private write<T extends Struct<unknown, unknown>>(type: T, value: StructInitType<T>) { private write<T extends Struct<object, object, unknown>>(
type: T,
value: StructInitType<T>
) {
return this.stream.write(type.serialize(value, this.stream.backend)); return this.stream.write(type.serialize(value, this.stream.backend));
} }
} }

View file

@ -1,17 +1,21 @@
import { Array, BackingField, FieldDescriptorBase, FieldDescriptorBaseOptions, FieldType, FixedLengthArray, getFieldTypeDefinition, Number, StructDeserializationContext, StructOptions, StructSerializationContext, VariableLengthArray } from './field'; import { Array, BackingField, FieldDescriptorBase, FieldDescriptorBaseOptions, FieldType, FixedLengthArray, getFieldTypeDefinition, Number, StructDeserializationContext, StructOptions, StructSerializationContext, VariableLengthArray } from './field';
import { Evaluate, Identity } from './utils'; import { Evaluate, Identity } from './utils';
export type StructValueType<T extends Struct<unknown, unknown, unknown>> = export type StructValueType<T extends Struct<object, object, unknown>> =
T extends { deserialize(reader: StructDeserializationContext): Promise<infer R>; } ? R : never; T extends { deserialize(reader: StructDeserializationContext): Promise<infer R>; } ? R : never;
export type StructInitType<T extends Struct<unknown, unknown, unknown>> = export type StructInitType<T extends Struct<object, object, unknown>> =
T extends { create(value: infer R, ...args: any): any; } ? R : never; T extends { create(value: infer R, ...args: any): any; } ? R : never;
export const StructDefaultOptions: Readonly<StructOptions> = { export const StructDefaultOptions: Readonly<StructOptions> = {
littleEndian: false, littleEndian: false,
}; };
interface AddArrayFieldDescriptor<TObject, TAfterParsed, TInit> { interface AddArrayFieldDescriptor<
TResult extends object,
TInit extends object,
TAfterParsed
> {
< <
TName extends string, TName extends string,
TType extends Array.SubType, TType extends Array.SubType,
@ -22,9 +26,9 @@ interface AddArrayFieldDescriptor<TObject, TAfterParsed, TInit> {
options: FixedLengthArray.Options, options: FixedLengthArray.Options,
typescriptType?: () => TTypeScriptType, typescriptType?: () => TTypeScriptType,
): MergeStruct< ): MergeStruct<
TObject, TResult,
TAfterParsed,
TInit, TInit,
TAfterParsed,
FixedLengthArray< FixedLengthArray<
TName, TName,
TType, TType,
@ -44,9 +48,9 @@ interface AddArrayFieldDescriptor<TObject, TAfterParsed, TInit> {
options: VariableLengthArray.Options<TInit, TLengthField, TEmptyBehavior>, options: VariableLengthArray.Options<TInit, TLengthField, TEmptyBehavior>,
typescriptType?: () => TTypeScriptType, typescriptType?: () => TTypeScriptType,
): MergeStruct< ): MergeStruct<
TObject, TResult,
TAfterParsed,
TInit, TInit,
TAfterParsed,
VariableLengthArray< VariableLengthArray<
TName, TName,
TType, TType,
@ -59,9 +63,9 @@ interface AddArrayFieldDescriptor<TObject, TAfterParsed, TInit> {
} }
interface AddArraySubTypeFieldDescriptor< interface AddArraySubTypeFieldDescriptor<
TObject, TResult extends object,
TInit extends object,
TAfterParsed, TAfterParsed,
TInit,
TType extends Array.SubType TType extends Array.SubType
> { > {
< <
@ -72,9 +76,9 @@ interface AddArraySubTypeFieldDescriptor<
options: FixedLengthArray.Options, options: FixedLengthArray.Options,
typescriptType?: () => TTypeScriptType, typescriptType?: () => TTypeScriptType,
): MergeStruct< ): MergeStruct<
TObject, TResult,
TAfterParsed,
TInit, TInit,
TAfterParsed,
FixedLengthArray< FixedLengthArray<
TName, TName,
TType, TType,
@ -92,9 +96,9 @@ interface AddArraySubTypeFieldDescriptor<
options: VariableLengthArray.Options<TInit, TLengthField, TEmptyBehavior>, options: VariableLengthArray.Options<TInit, TLengthField, TEmptyBehavior>,
_typescriptType?: () => TTypeScriptType, _typescriptType?: () => TTypeScriptType,
): MergeStruct< ): MergeStruct<
TObject, TResult,
TAfterParsed,
TInit, TInit,
TAfterParsed,
VariableLengthArray< VariableLengthArray<
TName, TName,
TType, TType,
@ -106,22 +110,31 @@ interface AddArraySubTypeFieldDescriptor<
>; >;
} }
export type StructAfterParsed<TObject, TResult> = export type StructAfterParsed<TResult, TAfterParsed> =
(this: TObject, object: TObject) => TResult; (this: TResult, object: TResult) => TAfterParsed;
export type OmitNever<T> = Pick<T, { [K in keyof T]: [T[K]] extends [never] ? never : K }[keyof T]>; export type OmitNever<T> = Pick<T, { [K in keyof T]: [T[K]] extends [never] ? never : K }[keyof T]>;
type MergeStruct<TObject, TAfterParsed, TInit, TDescriptor extends FieldDescriptorBase> = type MergeStruct<
TResult extends object,
TInit extends object,
TAfterParsed,
TDescriptor extends FieldDescriptorBase
> =
Identity<Struct< Identity<Struct<
Evaluate<TObject & Exclude<TDescriptor['resultObject'], undefined>>, Evaluate<TResult & Exclude<TDescriptor['resultObject'], undefined>>,
TAfterParsed, Evaluate<OmitNever<TInit & Exclude<TDescriptor['initObject'], undefined>>>,
Evaluate<OmitNever<TInit & Exclude<TDescriptor['initObject'], undefined>>> TAfterParsed
>>; >>;
export type StructExtraResult<TObject, TExtra> = export type StructExtraResult<TResult, TExtra> =
Evaluate<Omit<TObject, keyof TExtra> & TExtra>; Evaluate<Omit<TResult, keyof TExtra> & TExtra>;
export default class Struct<TObject = {}, TAfterParsed = undefined, TInit = {}> { export default class Struct<
TResult extends object = {},
TInit extends object = {},
TAfterParsed = undefined,
> {
public readonly options: Readonly<StructOptions>; public readonly options: Readonly<StructOptions>;
private _size = 0; private _size = 0;
@ -148,7 +161,7 @@ export default class Struct<TObject = {}, TAfterParsed = undefined, TInit = {}>
public field<TDescriptor extends FieldDescriptorBase>( public field<TDescriptor extends FieldDescriptorBase>(
field: TDescriptor, field: TDescriptor,
): MergeStruct<TObject, TAfterParsed, TInit, TDescriptor> { ): MergeStruct<TResult, TInit, TAfterParsed, TDescriptor> {
const result = this.clone(); const result = this.clone();
result.fields.push(field); result.fields.push(field);
@ -208,7 +221,7 @@ export default class Struct<TObject = {}, TAfterParsed = undefined, TInit = {}>
); );
} }
private array: AddArrayFieldDescriptor<TObject, TAfterParsed, TInit> = ( private array: AddArrayFieldDescriptor<TResult, TInit, TAfterParsed> = (
name: string, name: string,
type: Array.SubType, type: Array.SubType,
options: FixedLengthArray.Options | VariableLengthArray.Options options: FixedLengthArray.Options | VariableLengthArray.Options
@ -231,9 +244,9 @@ export default class Struct<TObject = {}, TAfterParsed = undefined, TInit = {}>
}; };
public arrayBuffer: AddArraySubTypeFieldDescriptor< public arrayBuffer: AddArraySubTypeFieldDescriptor<
TObject, TResult,
TAfterParsed,
TInit, TInit,
TAfterParsed,
Array.SubType.ArrayBuffer Array.SubType.ArrayBuffer
> = <TName extends string>( > = <TName extends string>(
name: TName, name: TName,
@ -243,9 +256,9 @@ export default class Struct<TObject = {}, TAfterParsed = undefined, TInit = {}>
}; };
public string: AddArraySubTypeFieldDescriptor< public string: AddArraySubTypeFieldDescriptor<
TObject, TResult,
TAfterParsed,
TInit, TInit,
TAfterParsed,
Array.SubType.String Array.SubType.String
> = <TName extends string>( > = <TName extends string>(
name: TName, name: TName,
@ -255,11 +268,11 @@ export default class Struct<TObject = {}, TAfterParsed = undefined, TInit = {}>
}; };
public extra<TExtra extends object>( public extra<TExtra extends object>(
value: TExtra & ThisType<StructExtraResult<TObject, TExtra>> value: TExtra & ThisType<StructExtraResult<TResult, TExtra>>
): Struct< ): Struct<
StructExtraResult<TObject, TExtra>, StructExtraResult<TResult, TExtra>,
TAfterParsed, Evaluate<Omit<TInit, keyof TExtra>>,
Evaluate<Omit<TInit, keyof TExtra>> TAfterParsed
> { > {
const result = this.clone(); const result = this.clone();
result._extra = { ...result._extra, ...Object.getOwnPropertyDescriptors(value) }; result._extra = { ...result._extra, ...Object.getOwnPropertyDescriptors(value) };
@ -267,23 +280,23 @@ export default class Struct<TObject = {}, TAfterParsed = undefined, TInit = {}>
} }
public afterParsed( public afterParsed(
callback: StructAfterParsed<TObject, never> callback: StructAfterParsed<TResult, never>
): Struct<TObject, never, TInit>; ): Struct<TResult, TInit, never>;
public afterParsed( public afterParsed(
callback?: StructAfterParsed<TObject, void> callback?: StructAfterParsed<TResult, void>
): Struct<TObject, undefined, TInit>; ): Struct<TResult, TInit, undefined>;
public afterParsed<TResult>( public afterParsed<TAfterParsed>(
callback?: StructAfterParsed<TObject, TResult> callback?: StructAfterParsed<TResult, TAfterParsed>
): Struct<TObject, TResult, TInit>; ): Struct<TResult, TInit, TAfterParsed>;
public afterParsed( public afterParsed(
callback?: StructAfterParsed<TObject, any> callback?: StructAfterParsed<TResult, any>
): Struct<any, any, any> { ): Struct<any, any, any> {
const result = this.clone(); const result = this.clone();
result._afterParsed = callback; result._afterParsed = callback;
return result; return result;
} }
public create(init: TInit, context: StructSerializationContext): TObject { public create(init: TInit, context: StructSerializationContext): TResult {
const object: any = { const object: any = {
[BackingField]: {}, [BackingField]: {},
}; };
@ -309,7 +322,7 @@ export default class Struct<TObject = {}, TAfterParsed = undefined, TInit = {}>
public async deserialize( public async deserialize(
context: StructDeserializationContext context: StructDeserializationContext
): Promise<TAfterParsed extends undefined ? TObject : TAfterParsed> { ): Promise<TAfterParsed extends undefined ? TResult : TAfterParsed> {
const object: any = { const object: any = {
[BackingField]: {}, [BackingField]: {},
}; };