enum.ts 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940
  1. import type {CodeKeywordDefinition} from "../../types"
  2. import type KeywordCxt from "../../compile/context"
  3. import {_, or, not, Code} from "../../compile/codegen"
  4. import {checkMetadata} from "./metadata"
  5. const def: CodeKeywordDefinition = {
  6. keyword: "enum",
  7. schemaType: "array",
  8. code(cxt: KeywordCxt) {
  9. checkMetadata(cxt)
  10. const {gen, data, schema, schemaValue, parentSchema, it} = cxt
  11. if (schema.length === 0) throw new Error("enum must have non-empty array")
  12. if (schema.length !== new Set(schema).size) throw new Error("enum items must be unique")
  13. let valid: Code
  14. if (schema.length >= it.opts.loopEnum) {
  15. if (parentSchema.nullable) {
  16. valid = gen.let("valid", _`${data} === null`)
  17. gen.if(not(valid), loopEnum)
  18. } else {
  19. valid = gen.let("valid", false)
  20. loopEnum()
  21. }
  22. } else {
  23. /* istanbul ignore if */
  24. if (!Array.isArray(schema)) throw new Error("ajv implementation error")
  25. valid = or(...schema.map((value: string) => _`${data} === ${value}`))
  26. if (parentSchema.nullable) valid = or(_`${data} === null`, valid)
  27. }
  28. cxt.pass(valid)
  29. function loopEnum(): void {
  30. gen.forOf("v", schemaValue as Code, (v) =>
  31. gen.if(_`${valid} = ${data} === ${v}`, () => gen.break())
  32. )
  33. }
  34. },
  35. }
  36. export default def