Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-validator

Typed fluent validation rules for Pudu

0.1.1Apache-2.01

InstallClose

Advanced.pudu

Pudu45 lines2.0 KB

GitHub ↗
1/** @Validation.Advanced.Control — composes custom and dependent rules */2module PuduLangValidator.Advanced34import PuduLangValidator.Result as Validation5import PuduLangValidator.Rule as Rule67/// Use application code to report zero or more structured failures.8export fn custom[T](name: Str, check: fn(T) -> Array[Validation.Failure]) -> Rule.Rule[T] {9  customWithContext(name, fn(root: T, _data: Rule.ContextData) -> Array[Validation.Failure] { check(root) })10}1112/// Use immutable context data to report structured failures.13export fn customWithContext[T](14  name: Str, check: fn(T, Rule.ContextData) -> Array[Validation.Failure]15) -> Rule.Rule[T] {16  Rule.Rule{name: name, ruleSets: [], run: fn(root: T, _sets: Array[Str], _defaults: Bool, _properties: Array[Str], data: Rule.ContextData) -> Array[Validation.Failure] {17      check(root, data)18    } }19}2021/// Run a dependent rule only after its prerequisite succeeds.22export fn dependent[T](primary: Rule.Rule[T], next: Rule.Rule[T]) -> Rule.Rule[T] {23  let name = primary.name24  let sets = primary.ruleSets25  Rule.Rule{name: name, ruleSets: sets, run: fn(root: T, selected: Array[Str], includeDefault: Bool, properties: Array[Str], data: Rule.ContextData) -> Array[Validation.Failure] {26      let first = primary.run(root, selected, includeDefault, properties, data)27      if !first.isEmpty() { return first }28      next.run(root, selected, includeDefault, properties, data)29    } }30}3132/// Run a built rule only when its source condition holds.33export fn when[T](rule: Rule.Rule[T], condition: fn(T) -> Bool) -> Rule.Rule[T] {34  let name = rule.name35  let sets = rule.ruleSets36  Rule.Rule{name: name, ruleSets: sets, run: fn(root: T, selected: Array[Str], includeDefault: Bool, properties: Array[Str], data: Rule.ContextData) -> Array[Validation.Failure] {37      if condition(root) { rule.run(root, selected, includeDefault, properties, data) } else { [] }38    } }39}4041/// Skip a built rule when its source condition holds.42export fn unless[T](rule: Rule.Rule[T], condition: fn(T) -> Bool) -> Rule.Rule[T] {43  when(rule, fn(root: T) -> Bool { !condition(root) })44}45