You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					55 lines
				
				1.8 KiB
			
		
		
			
		
	
	
					55 lines
				
				1.8 KiB
			| 
											3 years ago
										 | import type {CodeKeywordDefinition, ErrorObject, KeywordErrorDefinition} from "../../types" | ||
|  | import type {KeywordCxt} from "../../compile/validate" | ||
|  | import {_, or, Name, Code} from "../../compile/codegen" | ||
|  | import {useFunc} from "../../compile/util" | ||
|  | import equal from "../../runtime/equal" | ||
|  | 
 | ||
|  | export type EnumError = ErrorObject<"enum", {allowedValues: any[]}, any[] | {$data: string}> | ||
|  | 
 | ||
|  | const error: KeywordErrorDefinition = { | ||
|  |   message: "must be equal to one of the allowed values", | ||
|  |   params: ({schemaCode}) => _`{allowedValues: ${schemaCode}}`, | ||
|  | } | ||
|  | 
 | ||
|  | const def: CodeKeywordDefinition = { | ||
|  |   keyword: "enum", | ||
|  |   schemaType: "array", | ||
|  |   $data: true, | ||
|  |   error, | ||
|  |   code(cxt: KeywordCxt) { | ||
|  |     const {gen, data, $data, schema, schemaCode, it} = cxt | ||
|  |     if (!$data && schema.length === 0) throw new Error("enum must have non-empty array") | ||
|  |     const useLoop = schema.length >= it.opts.loopEnum | ||
|  |     let eql: Name | undefined | ||
|  |     const getEql = (): Name => (eql ??= useFunc(gen, equal)) | ||
|  | 
 | ||
|  |     let valid: Code | ||
|  |     if (useLoop || $data) { | ||
|  |       valid = gen.let("valid") | ||
|  |       cxt.block$data(valid, loopEnum) | ||
|  |     } else { | ||
|  |       /* istanbul ignore if */ | ||
|  |       if (!Array.isArray(schema)) throw new Error("ajv implementation error") | ||
|  |       const vSchema = gen.const("vSchema", schemaCode) | ||
|  |       valid = or(...schema.map((_x: unknown, i: number) => equalCode(vSchema, i))) | ||
|  |     } | ||
|  |     cxt.pass(valid) | ||
|  | 
 | ||
|  |     function loopEnum(): void { | ||
|  |       gen.assign(valid, false) | ||
|  |       gen.forOf("v", schemaCode as Code, (v) => | ||
|  |         gen.if(_`${getEql()}(${data}, ${v})`, () => gen.assign(valid, true).break()) | ||
|  |       ) | ||
|  |     } | ||
|  | 
 | ||
|  |     function equalCode(vSchema: Name, i: number): Code { | ||
|  |       const sch = schema[i] | ||
|  |       return typeof sch === "object" && sch !== null | ||
|  |         ? _`${getEql()}(${data}, ${vSchema}[${i}])` | ||
|  |         : _`${data} === ${sch}` | ||
|  |     } | ||
|  |   }, | ||
|  | } | ||
|  | 
 | ||
|  | export default def |