1 import type {CodeKeywordDefinition, ErrorObject, KeywordErrorDefinition} from "../../types"
2 import type {KeywordCxt} from "../../compile/validate"
3 import {_, or, Name, Code} from "../../compile/codegen"
4 import {useFunc} from "../../compile/util"
5 import equal from "../../runtime/equal"
7 export type EnumError = ErrorObject<"enum", {allowedValues: any[]}, any[] | {$data: string}>
9 const error: KeywordErrorDefinition = {
10 message: "must be equal to one of the allowed values",
11 params: ({schemaCode}) => _`{allowedValues: ${schemaCode}}`,
14 const def: CodeKeywordDefinition = {
19 code(cxt: KeywordCxt) {
20 const {gen, data, $data, schema, schemaCode, it} = cxt
21 if (!$data && schema.length === 0) throw new Error("enum must have non-empty array")
22 const useLoop = schema.length >= it.opts.loopEnum
23 const eql = useFunc(gen, equal)
25 if (useLoop || $data) {
26 valid = gen.let("valid")
27 cxt.block$data(valid, loopEnum)
29 /* istanbul ignore if */
30 if (!Array.isArray(schema)) throw new Error("ajv implementation error")
31 const vSchema = gen.const("vSchema", schemaCode)
32 valid = or(...schema.map((_x: unknown, i: number) => equalCode(vSchema, i)))
36 function loopEnum(): void {
37 gen.assign(valid, false)
38 gen.forOf("v", schemaCode as Code, (v) =>
39 gen.if(_`${eql}(${data}, ${v})`, () => gen.assign(valid, true).break())
43 function equalCode(vSchema: Name, i: number): Code {
45 return typeof sch === "object" && sch !== null
46 ? _`${eql}(${data}, ${vSchema}[${i}])`
47 : _`${data} === ${sch}`