import {stringDecoder} from '../../coder/string/string-decoder.js'; import {stringEncoder} from '../../coder/string/string-encoder.js'; import {IncompatibleLiteralError} from '../../error/incompatible-literal-error.js'; import {InvalidBufferValueError} from '../../error/invalid-buffer-value-error.js'; import type {Decoding} from '../../type/decoding.js'; import type {Encoding} from '../../type/encoding.js'; import type {EnumDefinition} from '../../type/enum-definition.js'; import {extractEnumValues} from '../../util/extract-enum-values.js'; import {isString} from '../../util/guard/is-string.js'; import {isInSet} from '../../util/is-in-set.js'; import {ValueTransformer} from '../value/value-transformer.js'; export class EnumStringTransformer extends ValueTransformer< V, V > { public static fromDefinition( definition: EnumDefinition, ): EnumStringTransformer { return new EnumStringTransformer(extractEnumValues(definition)); } readonly #values: ReadonlySet; private constructor(values: ReadonlySet) { super(); this.#values = values; } public compatibleWith(data: unknown): data is V { return isString(data) && isInSet(data, this.#values); } public *decoder(): Decoding { const value: string = yield* stringDecoder(); if (!isInSet(value, this.#values)) { throw new InvalidBufferValueError(); } return value; } public encoder(data: V): Encoding { console.assert(isString(data) && isInSet(data, this.#values)); return stringEncoder(data); } public fromLiteral(literal: unknown): V { if (!isString(literal) || !isInSet(literal, this.#values)) { throw new IncompatibleLiteralError(); } return literal; } public toLiteral(data: V): unknown { console.assert(isString(data) && isInSet(data, this.#values)); return data; } }