Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

Commit

Permalink
does not work
Browse files Browse the repository at this point in the history
  • Loading branch information
KATT committed Oct 5, 2023
1 parent d82a911 commit f937e5d
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 47 deletions.
52 changes: 40 additions & 12 deletions src/async/asyncTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,29 @@ export type TsonAsyncStringifier = <TValue>(
space?: number,
) => TsonAsyncStringifierIterator<TValue>;
export type TsonAsyncIndex = TsonBranded<number, "AsyncRegistered">;
export interface TsonTransformerSerializeDeserializeAsync<TValue> {

export interface TsonTransformerSerializeDeserializeAsync<
TValue,
TSerializedValue,
> {
async: true;
/**
* From JSON-serializable value
*/
deserialize: (
v: TsonAsyncIndex,
register: (index: TsonAsyncIndex) => Promise<TValue>,
) => TValue;
deserialize: (opts: {
/**
* Abort signal from of the full stream
*/
abortSignal: Promise<never>;
/**
* Notify that we don't expect more values
*/
onDone: () => void;
/**
* Stream of values
*/
stream: AsyncIterable<TSerializedValue>;
}) => TValue;

/**
* The key to use when serialized
Expand All @@ -29,14 +43,24 @@ export interface TsonTransformerSerializeDeserializeAsync<TValue> {
/**
* JSON-serializable value
*/
serialize: (
v: TValue,
register: (thing: TValue) => TsonAsyncIndex,
) => TsonAsyncIndex;
serializeIterator: (opts: {
/**
* Abort signal from of the full stream
*/
abortSignal: AbortSignal;
/**
* Publish a value to the stream
*/
publish: (serialized: TSerializedValue) => void;
/**
* The value we're serializing
*/
value: TValue;
}) => AsyncIterable<TSerializedValue>;
}

export interface TsonAsyncType<TValue>
extends TsonTransformerSerializeDeserializeAsync<TValue>,
export interface TsonAsyncType<TValue, TSerializedValue>
extends TsonTransformerSerializeDeserializeAsync<TValue, TSerializedValue>,
TsonTypeTesterCustom {}
export interface TsonAsyncOptions {
/**
Expand All @@ -53,5 +77,9 @@ export interface TsonAsyncOptions {
/**
* The list of types to use
*/
types: (TsonAsyncType<any> | TsonType<any, any> | TsonType<any, never>)[];
types: (
| TsonAsyncType<any, any>
| TsonType<any, any>
| TsonType<any, never>
)[];
}
41 changes: 12 additions & 29 deletions src/async/serializeAsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,45 +31,28 @@ export type TsonAsyncValueTuple = [

function walkerFactory(nonce: TsonNonce, types: TsonAsyncOptions["types"]) {
// instance variables
let promiseIndex = 0 as TsonAsyncIndex;
const promiseIndex = 0 as TsonAsyncIndex;

Check failure on line 34 in src/async/serializeAsync.ts

View workflow job for this annotation

GitHub Actions / build

'promiseIndex' is declared but its value is never read.

Check failure on line 34 in src/async/serializeAsync.ts

View workflow job for this annotation

GitHub Actions / lint

'promiseIndex' is assigned a value but never used

Check failure on line 34 in src/async/serializeAsync.ts

View workflow job for this annotation

GitHub Actions / type_check

'promiseIndex' is declared but its value is never read.
const promises = new Map<TsonAsyncIndex, Promise<TsonAsyncValueTuple>>();

Check failure on line 35 in src/async/serializeAsync.ts

View workflow job for this annotation

GitHub Actions / build

'promises' is declared but its value is never read.

Check failure on line 35 in src/async/serializeAsync.ts

View workflow job for this annotation

GitHub Actions / lint

'promises' is assigned a value but never used

Check failure on line 35 in src/async/serializeAsync.ts

View workflow job for this annotation

GitHub Actions / type_check

'promises' is declared but its value is never read.
const seen = new WeakSet();
const cache = new WeakMap<object, unknown>();

const iterators = new Map<
TsonAsyncIndex,
[TsonAsyncIndex, AsyncIterableIterator<TsonAsyncValueTuple>]
>();

const iterator = {
async *[Symbol.asyncIterator]() {

Check failure on line 45 in src/async/serializeAsync.ts

View workflow job for this annotation

GitHub Actions / lint

This generator function does not have 'yield'
while (promises.size > 0) {
const tuple = await Promise.race(promises.values());
while (iterators.size > 0) {
// race next() on all iterators

promises.delete(tuple[0]);
yield walk(tuple) as typeof tuple;
const nexts = Array.from(iterators.values()).map(([, iterator]) =>
iterator.next(),
);
const next = await Promise.race(nexts);

Check failure on line 52 in src/async/serializeAsync.ts

View workflow job for this annotation

GitHub Actions / build

'next' is declared but its value is never read.

Check failure on line 52 in src/async/serializeAsync.ts

View workflow job for this annotation

GitHub Actions / lint

'next' is assigned a value but never used

Check failure on line 52 in src/async/serializeAsync.ts

View workflow job for this annotation

GitHub Actions / type_check

'next' is declared but its value is never read.
}
},
};
// helper fns
function registerPromise(promise: Promise<unknown>): TsonAsyncIndex {
const index = promiseIndex++ as TsonAsyncIndex;
promises.set(
index,
promise
.then((result) => {
const tuple: TsonAsyncValueTuple = [index, PROMISE_RESOLVED, result];
return tuple;
})
// ^?
.catch((err) => {
const tuple: TsonAsyncValueTuple = [
index,
PROMISE_REJECTED,
new TsonPromiseRejectionError(err),
];

return tuple;
}),
);

return index;
}

const handlers = (() => {
const all = types.map((handler) => {
Expand Down
103 changes: 97 additions & 6 deletions src/handlers/tsonPromise.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,104 @@
import { TsonAsyncType } from "../async/asyncTypes.js";

function isPromiseLike(value: unknown): value is PromiseLike<unknown> {
return typeof value === "object" && value !== null && "then" in value;
function isPromise(value: unknown): value is Promise<unknown> {
return (
!!value &&
typeof value === "object" &&
"then" in value &&
typeof (value as any).catch === "function"
);
}

export const tsonPromise: TsonAsyncType<PromiseLike<unknown>> = {
const PROMISE_RESOLVED = 0;
const PROMISE_REJECTED = 1;

type SerializedPromiseValue =
| [typeof PROMISE_REJECTED, unknown]
| [typeof PROMISE_RESOLVED, unknown];

type MyPromise = Promise<SerializedPromiseValue>;

export const tsonPromise: TsonAsyncType<MyPromise, SerializedPromiseValue> = {
async: true,
deserialize: (idx, register) => register(idx),
deserialize: (opts) => {
return new Promise((resolve, reject) => {
async function _handle() {
const value = await Promise.race([
opts.stream[Symbol.asyncIterator]().next(),
opts.abortSignal,
]);

resolve(value.value as SerializedPromiseValue);
opts.onDone();
}

void _handle().catch(reject);
});
},
key: "Promise",
serialize: (value, register) => register(value),
test: isPromiseLike,
serializeIterator: async function* serialize(opts) {
const value = await opts.value
.then((value): SerializedPromiseValue => [PROMISE_RESOLVED, value])
.catch((err): SerializedPromiseValue => [PROMISE_REJECTED, err]);

yield value;
},
test: isPromise,
};

const ITERATOR_VALUE = 0;
const ITERATOR_ERROR = 1;
const ITERATOR_DONE = 2;

type SerializedIteratorResult =
| [typeof ITERATOR_DONE]
| [typeof ITERATOR_ERROR, unknown]
| [typeof ITERATOR_VALUE, unknown];

function isAsyncIterator(value: unknown): value is AsyncIterable<unknown> {
return (
!!value &&
typeof value === "object" &&
typeof (value as any)[Symbol.asyncIterator] === "function"
);
}

export const tsonAsyncIterator: TsonAsyncType<
AsyncIterable<unknown>,
SerializedIteratorResult
> = {
async: true,
deserialize: (opts) => {
return (async function* generator() {
for await (const value of opts.stream) {
switch (value[0]) {
case ITERATOR_DONE: {
return;
}

case ITERATOR_ERROR: {
throw value[1];
}

case ITERATOR_VALUE: {
yield value[1];
break;
}
}
}
})();
},
key: "AsyncIterator",
serializeIterator: async function* serialize(opts) {
try {
for await (const value of opts.value) {
yield [ITERATOR_VALUE, value];
}

yield [ITERATOR_DONE];
} catch (err) {
yield [ITERATOR_ERROR, err];
}
},
test: isAsyncIterator,
};
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type SerializedType =
| unknown[];

export interface TsonTransformerNone {
async?: false;
deserialize?: never;

/**
Expand Down

0 comments on commit f937e5d

Please sign in to comment.