moonlight-delta-0.1.0.0: src-patch/Moonlight/Delta/Patch/Internal/Compose/Aligned.hs
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
module Moonlight.Delta.Patch.Internal.Compose.Aligned
( tryAlignedTree,
tryAlignedPage,
)
where
import Data.Map.Internal qualified as MapInternal
import Data.Map.Strict qualified as Map
import Moonlight.Delta.Patch.Internal.Cell
( endpointToMaybe,
)
import Moonlight.Delta.Patch.Internal.Page
import Moonlight.Delta.Patch.Internal.Types
import Prelude
tryAlignedTree ::
forall key value error.
(Ord key, Eq value) =>
(key -> Maybe value -> Maybe value -> error) ->
Map.Map key (Page key value) ->
Map.Map key (Page key value) ->
Either error (Maybe (Map.Map key (Page key value)))
tryAlignedTree makeBoundaryError =
go
where
go MapInternal.Tip MapInternal.Tip =
Right (Just MapInternal.Tip)
go
(MapInternal.Bin olderSize olderMaximum olderPage olderLeft olderRight)
(MapInternal.Bin newerSize newerMaximum newerPage newerLeft newerRight)
| olderSize /= newerSize =
Right Nothing
| compare olderMaximum newerMaximum /= EQ =
Right Nothing
| otherwise = do
maybeLeft <- go olderLeft newerLeft
case maybeLeft of
Nothing ->
Right Nothing
Just resultLeft -> do
maybePage <- tryAlignedPage makeBoundaryError olderMaximum olderPage newerMaximum newerPage
case maybePage of
Nothing ->
Right Nothing
Just (_, resultPage) -> do
maybeRight <- go olderRight newerRight
pure
( fmap
(\resultRight -> MapInternal.Bin newerSize newerMaximum resultPage resultLeft resultRight)
maybeRight
)
go _ _ =
Right Nothing
{-# INLINABLE tryAlignedTree #-}
tryAlignedPage ::
forall key value error.
(Ord key, Eq value) =>
(key -> Maybe value -> Maybe value -> error) ->
key ->
Page key value ->
key ->
Page key value ->
Either error (Maybe (key, Page key value))
tryAlignedPage makeBoundaryError olderMaximum olderPage newerMaximum newerPage =
case
validateAlignedPageBoundary
pageBoundaryError
olderMaximum
olderPage
(pageAfterColumn olderPage)
newerMaximum
newerPage
(pageBeforeColumn newerPage)
of
PageBoundaryMatched ->
Right
( Just
( newerMaximum,
newerPage {pageBeforeColumn = pageBeforeColumn olderPage}
)
)
PageBoundaryDiverged ->
Right Nothing
PageBoundaryRejected failure ->
Left failure
where
pageBoundaryError key olderAfter newerBefore =
makeBoundaryError key (endpointToMaybe olderAfter) (endpointToMaybe newerBefore)
{-# INLINABLE tryAlignedPage #-}