UNPKG

1.77 kBPlain TextView Raw
1import type {CodeKeywordDefinition, ErrorObject, KeywordErrorDefinition} from "../../types"
2import type {KeywordCxt} from "../../compile/validate"
3import {_, or, Name, Code} from "../../compile/codegen"
4import {useFunc} from "../../compile/util"
5import equal from "../../runtime/equal"
6
7export type EnumError = ErrorObject<"enum", {allowedValues: any[]}, any[] | {$data: string}>
8
9const error: KeywordErrorDefinition = {
10 message: "must be equal to one of the allowed values",
11 params: ({schemaCode}) => _`{allowedValues: ${schemaCode}}`,
12}
13
14const def: CodeKeywordDefinition = {
15 keyword: "enum",
16 schemaType: "array",
17 $data: true,
18 error,
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)
24 let valid: Code
25 if (useLoop || $data) {
26 valid = gen.let("valid")
27 cxt.block$data(valid, loopEnum)
28 } else {
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)))
33 }
34 cxt.pass(valid)
35
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())
40 )
41 }
42
43 function equalCode(vSchema: Name, i: number): Code {
44 const sch = schema[i]
45 return typeof sch === "object" && sch !== null
46 ? _`${eql}(${data}, ${vSchema}[${i}])`
47 : _`${data} === ${sch}`
48 }
49 },
50}
51
52export default def