
PuduLangMediator.pudu
Pudu113 lines3.7 KB
1/** @Mediator.Root.Vocabulary — outcomes and failures of mediated messages */2module PuduLangMediator34import PuduLangMediator.Constants.Messages as Messages5import PuduLangMediator.Utils.Template as Template67/** @Mediator.Root.Violation — one rule a message broke */8export type Violation = { property: Str, message: Str, code: Str }910/** @Mediator.Root.Failure — why a mediated message produced no value */11export type Failure[E]12 = Raised(E)13 | Unhandled(Str)14 | Mismatched(Str)15 | Refused(Str)16 | Invalid(Array[Violation])17 | Cancelled(Str)18 | Crashed(Str)19 | Aggregate(Array[Failure[E]])2021/** @Mediator.Root.Outcome — the value or failure of one message */22export type Outcome[T, E] = Result[T, Failure[E]]232425export fn succeed[T, E](value: T) -> Outcome[T, E] { Ok(value) }262728export fn raise[T, E](problem: E) -> Outcome[T, E] { Err(Raised(problem)) }293031export fn refuse[T, E](reason: Str) -> Outcome[T, E] { Err(Refused(reason)) }323334export fn lift[T, E](result: Result[T, E]) -> Outcome[T, E] {35 match result {36 case Ok(value) => Ok(value)37 case Err(problem) => Err(Raised(problem))38 }39}404142export fn raised[E](failure: &Failure[E]) -> Option[E] {43 match failure {44 case Raised(problem) => Some(problem)45 case _ => None46 }47}484950export fn isCancellation[E](failure: &Failure[E]) -> Bool {51 match failure {52 case Cancelled(_) => true53 case _ => false54 }55}565758export fn violations[E](failure: &Failure[E]) -> Array[Violation] {59 match failure {60 case Invalid(found) => found61 case Aggregate(parts) => {62 var found: Array[Violation] = []63 for part in parts { found = found.concat(violations(&part)) }64 found65 }66 case _ => []67 }68}697071export fn combine[E](failures: Array[Failure[E]]) -> Option[Failure[E]] {72 var flat: Array[Failure[E]] = []73 for failure in failures {74 match failure {75 case Aggregate(parts) => { flat = flat.concat(parts) }76 case single => { flat = flat.push(single) }77 }78 }79 match flat {80 case [] => None81 case [only] => Some(only)82 case _ => Some(Aggregate(flat))83 }84}858687export fn describe[E](failure: &Failure[E]) -> Str {88 match failure {89 case Raised(problem) => Template.fill(Messages.RAISED, &[show(problem)])90 case Unhandled(name) => Template.fill(Messages.UNHANDLED, &[name])91 case Mismatched(name) => Template.fill(Messages.MISMATCHED, &[name])92 case Refused(reason) => Template.fill(Messages.REFUSED, &[reason])93 case Invalid(found) => {94 let listed = found.map(|one: Violation| Template.fill(Messages.VIOLATION, &[one.property, one.message]))95 Template.fill(Messages.INVALID, &[listed.join(Messages.SEPARATOR)])96 }97 case Cancelled(reason) => Template.fill(Messages.CANCELLED, &[reason])98 case Crashed(reason) => Template.fill(Messages.CRASHED, &[reason])99 case Aggregate(parts) => {100 let listed = parts.map(|part: Failure[E]| describe(&part))101 Template.fill(Messages.AGGREGATE, &[show(parts.length()), listed.join(Messages.SEPARATOR)])102 }103 }104}105106107export fn summarize[T, E](outcome: &Outcome[T, E]) -> Str {108 match outcome {109 case Ok(value) => Template.fill(Messages.SUCCEEDED, &[show(value)])110 case Err(failure) => describe(&failure)111 }112}113