Skip to content

Commit

Permalink
feat: rename $.stringUnion to $.literalUnion (#137)
Browse files Browse the repository at this point in the history
  • Loading branch information
tjjfvi committed Feb 20, 2023
1 parent c931071 commit 5a6465a
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 30 deletions.
28 changes: 14 additions & 14 deletions codecs/test/__snapshots__/union.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -44,33 +44,33 @@ e7
00
`;

snapshot[`\$.stringUnion(names) "Ross" 1`] = `00`;
snapshot[`\$.literalUnion(names) "Ross" 1`] = `00`;

snapshot[`\$.stringUnion(names) "Alisa" 1`] = `01`;
snapshot[`\$.literalUnion(names) "Alisa" 1`] = `01`;

snapshot[`\$.stringUnion(names) "Stefan" 1`] = `02`;
snapshot[`\$.literalUnion(names) "Stefan" 1`] = `02`;

snapshot[`\$.stringUnion(names) "Raoul" 1`] = `03`;
snapshot[`\$.literalUnion(names) "Raoul" 1`] = `03`;

snapshot[`\$.stringUnion(names) "James" 1`] = `04`;
snapshot[`\$.literalUnion(names) "James" 1`] = `04`;

snapshot[`\$.stringUnion(names) "David" 1`] = `05`;
snapshot[`\$.literalUnion(names) "David" 1`] = `05`;

snapshot[`\$.stringUnion(names) "Pierre" 1`] = `06`;
snapshot[`\$.literalUnion(names) "Pierre" 1`] = `06`;

snapshot[`\$.stringUnion(interestingU8s) "Min" 1`] = `00`;
snapshot[`\$.literalUnion(interestingU8s) "Min" 1`] = `00`;

snapshot[`\$.stringUnion(interestingU8s) "Unit" 1`] = `01`;
snapshot[`\$.literalUnion(interestingU8s) "Unit" 1`] = `01`;

snapshot[`\$.stringUnion(interestingU8s) "EvenPrime" 1`] = `02`;
snapshot[`\$.literalUnion(interestingU8s) "EvenPrime" 1`] = `02`;

snapshot[`\$.stringUnion(interestingU8s) "LargestPerfect" 1`] = `1c`;
snapshot[`\$.literalUnion(interestingU8s) "LargestPerfect" 1`] = `1c`;

snapshot[`\$.stringUnion(interestingU8s) "FirstUninteresting" 1`] = `81`;
snapshot[`\$.literalUnion(interestingU8s) "FirstUninteresting" 1`] = `81`;

snapshot[`\$.stringUnion(interestingU8s) "LargestSquare" 1`] = `e1`;
snapshot[`\$.literalUnion(interestingU8s) "LargestSquare" 1`] = `e1`;

snapshot[`\$.stringUnion(interestingU8s) "Max" 1`] = `ff`;
snapshot[`\$.literalUnion(interestingU8s) "Max" 1`] = `ff`;

snapshot[`\$abc invalid null 1`] = `ScaleAssertError: value == null`;

Expand Down
4 changes: 2 additions & 2 deletions codecs/test/union.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const interestingU8s = {
255: "Max",
} as const

const $interestingU8s = $.withMetadata(metadata("$.stringUnion(interestingU8s)"), $.stringUnion(interestingU8s))
const $interestingU8s = $.withMetadata(metadata("$.literalUnion(interestingU8s)"), $.literalUnion(interestingU8s))

const names = [
"Ross",
Expand All @@ -34,7 +34,7 @@ const names = [
"Pierre",
] as const

const $names = $.withMetadata(metadata("$.stringUnion(names)"), $.stringUnion(names))
const $names = $.withMetadata(metadata("$.literalUnion(names)"), $.literalUnion(names))

testCodec($abc, [
{ _tag: "A" },
Expand Down
18 changes: 9 additions & 9 deletions codecs/union.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export type NativeTaggedUnion<

export function taggedUnion<
K extends keyof any,
M extends Record<number, Variant<any, any>>,
>(tagKey: K, members: Narrow<M>): Codec<NativeTaggedUnion<K, M>> {
M extends [] | Record<number, Variant<any, any>>,
>(tagKey: K, members: M): Codec<NativeTaggedUnion<K, M>> {
const tagToDiscriminant: Record<string, number> = Object.create(null)
const discriminantToMember: Record<number, Codec<any>> = Object.create(null)
for (const _discriminant in members) {
Expand Down Expand Up @@ -65,19 +65,19 @@ export function taggedUnion<
})
}

export function stringUnion<T extends string>(members: Record<number, T>): Codec<T> {
const keyToDiscriminant: Record<string, number> = Object.create(null)
export function literalUnion<T extends Narrow>(members: Record<number, T>): Codec<T> {
const keyToDiscriminant: Map<T, number> = new Map()
for (const _discriminant in members) {
const discriminant = +_discriminant
if (isNaN(discriminant)) continue
const key = members[discriminant]!
keyToDiscriminant[key] = discriminant
const key = members[discriminant] as T
keyToDiscriminant.set(key, discriminant)
}
return createCodec({
_metadata: metadata("$.stringUnion", stringUnion, members),
_metadata: metadata("$.literalUnion", literalUnion, members),
_staticSize: 1,
_encode(buffer, value) {
const discriminant = keyToDiscriminant[value]!
const discriminant = keyToDiscriminant.get(value)!
buffer.array[buffer.index++] = discriminant
},
_decode(buffer) {
Expand All @@ -86,7 +86,7 @@ export function stringUnion<T extends string>(members: Record<number, T>): Codec
},
_assert(assert) {
assert.typeof(this, "string")
if (!((assert.value as string) in keyToDiscriminant)) {
if (!keyToDiscriminant.has(assert.value as T)) {
throw new ScaleAssertError(this, assert.value, `${assert.path} invalid value`)
}
},
Expand Down
16 changes: 12 additions & 4 deletions common/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,15 @@ export class ScaleDecodeError extends ScaleError {

export type Expand<T> = T extends T ? { [K in keyof T]: T[K] } : never
export type U2I<U> = (U extends U ? (u: U) => 0 : never) extends (i: infer I) => 0 ? Extract<I, U> : never
export type Narrow<T> =
| (T extends infer U ? U : never)
| Extract<T, number | string | boolean | bigint | symbol | null | undefined | []>
| ([T] extends [[]] ? [] : { [K in keyof T]: Narrow<T[K]> })

type _Narrow<T, U> = [U] extends [T] ? U : Extract<T, U>
export type Narrow<T = unknown> =
| _Narrow<T, 0 | number & {}>
| _Narrow<T, 0n | bigint & {}>
| _Narrow<T, "" | string & {}>
| _Narrow<T, boolean>
| _Narrow<T, symbol>
| _Narrow<T, []>
| _Narrow<T, { [_: PropertyKey]: Narrow }>
| (T extends object ? { [K in keyof T]: Narrow<T[K]> } : never)
| Extract<{} | null | undefined, T>
2 changes: 1 addition & 1 deletion examples/unions.eg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ $pet
// | { type: "cat"; purr: string; name: string }
// >

export const $dinosaur = $.stringUnion([
export const $dinosaur = $.literalUnion([
"Liopleurodon",
"Kosmoceratops",
"Psittacosaurus",
Expand Down

0 comments on commit 5a6465a

Please sign in to comment.