{{
  var $schema = it.schema[$rule.keyword]
    , $ruleValidate = it.useCustomRule($rule, $schema, it.schema, it)
    , $ruleErrs = $ruleValidate.code + '.errors'
    , $schemaPath = it.schemaPath + '.' + $rule.keyword
    , $errSchemaPath = it.errSchemaPath + '/' + $rule.keyword
    , $errs = 'errs' + $lvl
    , $i = 'i' + $lvl
    , $ruleErr = 'ruleErr' + $lvl
    , $rDef = $rule.definition
    , $asyncKeyword = $rDef.async
    , $inline = $rDef.inline
    , $macro = $rDef.macro;

  if ($asyncKeyword && !it.async)
    throw new Error('async keyword in sync schema');
}}

{{? !($inline || $macro) }}{{=$ruleErrs}} = null;{{?}}
var {{=$errs}} = errors;
var valid{{=$lvl}};

{{## def.callRuleValidate:
  {{=$ruleValidate.code}}.call(
    {{? it.opts.passContext }}this{{??}}self{{?}}
    {{ var $validateArgs = $ruleValidate.validate.length; }}
    {{? $rDef.compile || $rDef.schema === false }}
      , {{=$data}}
    {{??}}
      , validate.schema{{=$schemaPath}}
      , {{=$data}}
      , validate.schema{{=it.schemaPath}}
    {{?}}
    , {{# def.dataPath }}
    {{# def.passParentData }}
  )
#}}

{{## def.ruleValidationResult:
  {{? $inline }}
    {{? $rDef.statements }}
      valid{{=$lvl}}
    {{??}}
      ({{= $ruleValidate.validate }})
    {{?}}
  {{?? $macro }}
    valid{{=$it.level}}
  {{??}}
    {{? $asyncKeyword }}
      {{? $rDef.errors === false }}
        ({{=it.yieldAwait}}{{= def_callRuleValidate }})
      {{??}}
        valid{{=$lvl}}
      {{?}}
    {{??}}
      {{= def_callRuleValidate }}
    {{?}}
  {{?}}
#}}

{{## def.extendErrors:_inline:
  for (var {{=$i}}={{=$errs}}; {{=$i}}<errors; {{=$i}}++) {
    var {{=$ruleErr}} = vErrors[{{=$i}}];
    {{# _inline ? 'if (\{\{=$ruleErr\}\}.dataPath === undefined) {' : '' }}
      {{=$ruleErr}}.dataPath = (dataPath || '') + {{= it.errorPath }};
    {{# _inline ? '}' : '' }}
    {{# _inline ? 'if (\{\{=$ruleErr\}\}.schemaPath === undefined) {' : '' }}
      {{=$ruleErr}}.schemaPath = "{{=$errSchemaPath}}";
    {{# _inline ? '}' : '' }}
    {{? it.opts.verbose }}
      {{=$ruleErr}}.schema = validate.schema{{=$schemaPath}};
      {{=$ruleErr}}.data = {{=$data}};
    {{?}}
  }
#}}

{{? $inline && $rDef.statements }}
  {{= $ruleValidate.validate }}
{{?? $macro }}
  {{# def.setupNextLevel }}
  {{
    $it.schema = $ruleValidate.validate;
    $it.schemaPath = '';
  }}
  {{# def.setCompositeRule }}
  {{ var $code = it.validate($it).replace(/validate\.schema/g, $ruleValidate.code); }}
  {{# def.resetCompositeRule }}
  {{= $code }}
{{?? $rDef.compile || $rDef.validate }}
  {{# def.beginDefOut}}
    {{# def.callRuleValidate }}
  {{# def.storeDefOut:def_callRuleValidate }}

  {{? $rDef.errors !== false }}
    {{? $asyncKeyword }}
      {{ $ruleErrs = 'customErrors' + $lvl; }}
      var {{=$ruleErrs}} = null;
      try {
        valid{{=$lvl}} = {{=it.yieldAwait}}{{= def_callRuleValidate }};
      } catch (e) {
        valid{{=$lvl}} = false;
        if (e instanceof ValidationError) {{=$ruleErrs}} = e.errors;
        else throw e;
      }
    {{??}}
      {{=$ruleValidate.code}}.errors = null;
    {{?}}
  {{?}}
{{?}}


if (!{{# def.ruleValidationResult }}) {
  {{ $errorKeyword = $rule.keyword; }}
  {{# def.beginDefOut}}
    {{# def.error:'custom' }}
  {{# def.storeDefOut:def_customError }}

  {{? $inline }}
    {{? $rDef.errors }}
      {{? $rDef.errors != 'full' }}
        {{# def.extendErrors:true }}
      {{?}}
    {{??}}
      {{? $rDef.errors === false}}
        {{= def_customError }}
      {{??}}
        if ({{=$errs}} == errors) {
          {{= def_customError }}
        } else {
          {{# def.extendErrors:true }}
        }
      {{?}}
    {{?}}
  {{?? $macro}}
    {{# def.extraError:'custom' }}
  {{??}}
    {{? $rDef.errors === false}}
      {{= def_customError }}
    {{??}}
      if (Array.isArray({{=$ruleErrs}})) {
        if (vErrors === null) vErrors = {{=$ruleErrs}};
        else vErrors.concat({{=$ruleErrs}});
        errors = vErrors.length;
        {{# def.extendErrors:false }}
      } else {
        {{= def_customError }}
      }
    {{?}}
  {{?}}
  {{ $errorKeyword = undefined; }}

 } {{? $breakOnError }} else { {{?}}
