{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Basement.MutableBuilder
    ( Builder(..)
    , BuildingState(..)
    ) where

import           Basement.Compat.Base
import           Basement.Compat.MonadTrans
import           Basement.Types.OffsetSize
import           Basement.Monad

newtype Builder collection mutCollection step state err a = Builder
    { Builder collection mutCollection step state err a
-> State
     (Offset step,
      BuildingState collection mutCollection step (PrimState state),
      Maybe err)
     state
     a
runBuilder :: State (Offset step, BuildingState collection mutCollection step (PrimState state), Maybe err) state a }
    deriving (a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err a
(a -> b)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
(forall a b.
 (a -> b)
 -> Builder collection mutCollection step state err a
 -> Builder collection mutCollection step state err b)
-> (forall a b.
    a
    -> Builder collection mutCollection step state err b
    -> Builder collection mutCollection step state err a)
-> Functor (Builder collection mutCollection step state err)
forall a b.
a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err a
forall a b.
(a -> b)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err a
forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
(a -> b)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err a
$c<$ :: forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err a
fmap :: (a -> b)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
$cfmap :: forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
(a -> b)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
Functor, Functor (Builder collection mutCollection step state err)
a -> Builder collection mutCollection step state err a
Functor (Builder collection mutCollection step state err)
-> (forall a.
    a -> Builder collection mutCollection step state err a)
-> (forall a b.
    Builder collection mutCollection step state err (a -> b)
    -> Builder collection mutCollection step state err a
    -> Builder collection mutCollection step state err b)
-> (forall a b c.
    (a -> b -> c)
    -> Builder collection mutCollection step state err a
    -> Builder collection mutCollection step state err b
    -> Builder collection mutCollection step state err c)
-> (forall a b.
    Builder collection mutCollection step state err a
    -> Builder collection mutCollection step state err b
    -> Builder collection mutCollection step state err b)
-> (forall a b.
    Builder collection mutCollection step state err a
    -> Builder collection mutCollection step state err b
    -> Builder collection mutCollection step state err a)
-> Applicative (Builder collection mutCollection step state err)
Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err b
Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err a
Builder collection mutCollection step state err (a -> b)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
(a -> b -> c)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err c
forall a. a -> Builder collection mutCollection step state err a
forall a b.
Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err a
forall a b.
Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err b
forall a b.
Builder collection mutCollection step state err (a -> b)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
forall a b c.
(a -> b -> c)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err c
forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err.
Monad state =>
Functor (Builder collection mutCollection step state err)
forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a.
Monad state =>
a -> Builder collection mutCollection step state err a
forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err a
forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err b
forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
Builder collection mutCollection step state err (a -> b)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b c.
Monad state =>
(a -> b -> c)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err a
$c<* :: forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err a
*> :: Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err b
$c*> :: forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err b
liftA2 :: (a -> b -> c)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err c
$cliftA2 :: forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b c.
Monad state =>
(a -> b -> c)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err c
<*> :: Builder collection mutCollection step state err (a -> b)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
$c<*> :: forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
Builder collection mutCollection step state err (a -> b)
-> Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
pure :: a -> Builder collection mutCollection step state err a
$cpure :: forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a.
Monad state =>
a -> Builder collection mutCollection step state err a
$cp1Applicative :: forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err.
Monad state =>
Functor (Builder collection mutCollection step state err)
Applicative, Applicative (Builder collection mutCollection step state err)
a -> Builder collection mutCollection step state err a
Applicative (Builder collection mutCollection step state err)
-> (forall a b.
    Builder collection mutCollection step state err a
    -> (a -> Builder collection mutCollection step state err b)
    -> Builder collection mutCollection step state err b)
-> (forall a b.
    Builder collection mutCollection step state err a
    -> Builder collection mutCollection step state err b
    -> Builder collection mutCollection step state err b)
-> (forall a.
    a -> Builder collection mutCollection step state err a)
-> Monad (Builder collection mutCollection step state err)
Builder collection mutCollection step state err a
-> (a -> Builder collection mutCollection step state err b)
-> Builder collection mutCollection step state err b
Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err b
forall a. a -> Builder collection mutCollection step state err a
forall a b.
Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err b
forall a b.
Builder collection mutCollection step state err a
-> (a -> Builder collection mutCollection step state err b)
-> Builder collection mutCollection step state err b
forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err.
Monad state =>
Applicative (Builder collection mutCollection step state err)
forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a.
Monad state =>
a -> Builder collection mutCollection step state err a
forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err b
forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
Builder collection mutCollection step state err a
-> (a -> Builder collection mutCollection step state err b)
-> Builder collection mutCollection step state err b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> Builder collection mutCollection step state err a
$creturn :: forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a.
Monad state =>
a -> Builder collection mutCollection step state err a
>> :: Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err b
$c>> :: forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
Builder collection mutCollection step state err a
-> Builder collection mutCollection step state err b
-> Builder collection mutCollection step state err b
>>= :: Builder collection mutCollection step state err a
-> (a -> Builder collection mutCollection step state err b)
-> Builder collection mutCollection step state err b
$c>>= :: forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a b.
Monad state =>
Builder collection mutCollection step state err a
-> (a -> Builder collection mutCollection step state err b)
-> Builder collection mutCollection step state err b
$cp1Monad :: forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err.
Monad state =>
Applicative (Builder collection mutCollection step state err)
Monad)

-- | The in-progress state of a building operation.
--
-- The previous buffers are in reverse order, and
-- this contains the current buffer and the state of
-- progress packing the elements inside.
data BuildingState collection mutCollection step state = BuildingState
    { BuildingState collection mutCollection step state -> [collection]
prevChunks     :: [collection]
    , BuildingState collection mutCollection step state -> CountOf step
prevChunksSize :: !(CountOf step)
    , BuildingState collection mutCollection step state
-> mutCollection state
curChunk       :: mutCollection state
    , BuildingState collection mutCollection step state -> CountOf step
chunkSize      :: !(CountOf step)
    }

instance Monad state => MonadFailure (Builder collection mutCollection step state err) where
    type Failure (Builder collection mutCollection step state err) = err
    mFail :: Failure (Builder collection mutCollection step state err)
-> Builder collection mutCollection step state err ()
mFail Failure (Builder collection mutCollection step state err)
builderError = State
  (Offset step,
   BuildingState collection mutCollection step (PrimState state),
   Maybe err)
  state
  ()
-> Builder collection mutCollection step state err ()
forall collection (mutCollection :: * -> *) step (state :: * -> *)
       err a.
State
  (Offset step,
   BuildingState collection mutCollection step (PrimState state),
   Maybe err)
  state
  a
-> Builder collection mutCollection step state err a
Builder (State
   (Offset step,
    BuildingState collection mutCollection step (PrimState state),
    Maybe err)
   state
   ()
 -> Builder collection mutCollection step state err ())
-> State
     (Offset step,
      BuildingState collection mutCollection step (PrimState state),
      Maybe err)
     state
     ()
-> Builder collection mutCollection step state err ()
forall a b. (a -> b) -> a -> b
$ ((Offset step,
  BuildingState collection mutCollection step (PrimState state),
  Maybe err)
 -> state
      ((),
       (Offset step,
        BuildingState collection mutCollection step (PrimState state),
        Maybe err)))
-> State
     (Offset step,
      BuildingState collection mutCollection step (PrimState state),
      Maybe err)
     state
     ()
forall s (m :: * -> *) a. (s -> m (a, s)) -> State s m a
State (((Offset step,
   BuildingState collection mutCollection step (PrimState state),
   Maybe err)
  -> state
       ((),
        (Offset step,
         BuildingState collection mutCollection step (PrimState state),
         Maybe err)))
 -> State
      (Offset step,
       BuildingState collection mutCollection step (PrimState state),
       Maybe err)
      state
      ())
-> ((Offset step,
     BuildingState collection mutCollection step (PrimState state),
     Maybe err)
    -> state
         ((),
          (Offset step,
           BuildingState collection mutCollection step (PrimState state),
           Maybe err)))
-> State
     (Offset step,
      BuildingState collection mutCollection step (PrimState state),
      Maybe err)
     state
     ()
forall a b. (a -> b) -> a -> b
$ \(Offset step
offset, BuildingState collection mutCollection step (PrimState state)
bs, Maybe err
_)  ->
        ((),
 (Offset step,
  BuildingState collection mutCollection step (PrimState state),
  Maybe err))
-> state
     ((),
      (Offset step,
       BuildingState collection mutCollection step (PrimState state),
       Maybe err))
forall (m :: * -> *) a. Monad m => a -> m a
return ((), (Offset step
offset, BuildingState collection mutCollection step (PrimState state)
bs, err -> Maybe err
forall a. a -> Maybe a
Just err
Failure (Builder collection mutCollection step state err)
builderError))