import { orPatchInstruction } from "@tsplus/stdlib/data/Differ/OrPatch/definition" /** * Applies an or patch to a value to produce a new value which represents * the original value updated with the changes described by this patch. * * @tsplus static Differ.Or.Patch.Aspects apply * @tsplus pipeable Differ.Or.Patch apply */ export function apply( oldValue: Either, left: Differ, right: Differ ) { return (self: Differ.Or.Patch): Either => applyLoop(left, right, oldValue, List(self)) } /** * @tsplus tailRec */ function applyLoop( left: Differ, right: Differ, either: Either, patches: List> ): Either { if (patches.isNil()) { return either } const patch = orPatchInstruction(patches.head) const nextPatches = patches.tail switch (patch._tag) { case "AndThen": { return applyLoop(left, right, either, nextPatches.prepend(patch.second).prepend(patch.first)) } case "Empty": { return applyLoop(left, right, either, nextPatches) } case "UpdateLeft": { switch (either._tag) { case "Left": { return applyLoop( left, right, Either.left(left.patch(patch.patch, either.left)), nextPatches ) } case "Right": { return applyLoop(left, right, either, nextPatches) } } } case "UpdateRight": { switch (either._tag) { case "Left": { return applyLoop(left, right, either, nextPatches) } case "Right": { return applyLoop( left, right, Either.right(right.patch(patch.patch, either.right)), nextPatches ) } } } case "SetLeft": { return applyLoop(left, right, Either.left(patch.value), nextPatches) } case "SetRight": { return applyLoop(left, right, Either.right(patch.value), nextPatches) } } }