-- |
-- Module      : Foundation.Array.Mutable
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : experimental
-- Portability : portable
--
module Foundation.Collection.Mutable
    ( MutableCollection(..)
    ) where

import           Basement.Monad
import           Basement.Types.OffsetSize
import qualified Basement.Block         as BLK
import qualified Basement.Block.Mutable as BLK

import qualified Basement.UArray.Mutable as MUV
import qualified Basement.UArray as UV
import qualified Basement.BoxedArray as BA

-- | Collection of things that can be made mutable, modified and then freezed into an MutableFreezed collection
class MutableCollection c where
    -- unfortunately: cannot set mutUnsafeWrite to default to mutWrite .. same for read..
    {-# MINIMAL thaw, freeze, mutNew, mutWrite, mutRead, mutUnsafeWrite, mutUnsafeRead #-}
    type MutableFreezed c
    type MutableKey c
    type MutableValue c

    unsafeThaw   :: PrimMonad prim => MutableFreezed c -> prim (c (PrimState prim))
    unsafeThaw = MutableFreezed c -> prim (c (PrimState prim))
forall (c :: * -> *) (prim :: * -> *).
(MutableCollection c, PrimMonad prim) =>
MutableFreezed c -> prim (c (PrimState prim))
thaw
    unsafeFreeze :: PrimMonad prim => c (PrimState prim) -> prim (MutableFreezed c)
    unsafeFreeze = c (PrimState prim) -> prim (MutableFreezed c)
forall (c :: * -> *) (prim :: * -> *).
(MutableCollection c, PrimMonad prim) =>
c (PrimState prim) -> prim (MutableFreezed c)
freeze

    thaw   :: PrimMonad prim => MutableFreezed c -> prim (c (PrimState prim))
    freeze :: PrimMonad prim => c (PrimState prim) -> prim (MutableFreezed c)

    mutNew :: PrimMonad prim => CountOf (MutableValue c) -> prim (c (PrimState prim))

    mutUnsafeWrite :: PrimMonad prim => c (PrimState prim) -> MutableKey c -> MutableValue c -> prim ()
    mutWrite       :: PrimMonad prim => c (PrimState prim) -> MutableKey c -> MutableValue c -> prim ()
    mutUnsafeRead :: PrimMonad prim => c (PrimState prim) -> MutableKey c -> prim (MutableValue c)
    mutRead       :: PrimMonad prim => c (PrimState prim) -> MutableKey c -> prim (MutableValue c)

instance UV.PrimType ty => MutableCollection (MUV.MUArray ty) where
    type MutableFreezed (MUV.MUArray ty) = UV.UArray ty
    type MutableKey (MUV.MUArray ty) = Offset ty
    type MutableValue (MUV.MUArray ty) = ty

    thaw :: MutableFreezed (MUArray ty) -> prim (MUArray ty (PrimState prim))
thaw = MutableFreezed (MUArray ty) -> prim (MUArray ty (PrimState prim))
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
UArray ty -> prim (MUArray ty (PrimState prim))
UV.thaw
    freeze :: MUArray ty (PrimState prim) -> prim (MutableFreezed (MUArray ty))
freeze = MUArray ty (PrimState prim) -> prim (MutableFreezed (MUArray ty))
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MUArray ty (PrimState prim) -> prim (UArray ty)
UV.freeze
    unsafeThaw :: MutableFreezed (MUArray ty) -> prim (MUArray ty (PrimState prim))
unsafeThaw = MutableFreezed (MUArray ty) -> prim (MUArray ty (PrimState prim))
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
UArray ty -> prim (MUArray ty (PrimState prim))
UV.unsafeThaw
    unsafeFreeze :: MUArray ty (PrimState prim) -> prim (MutableFreezed (MUArray ty))
unsafeFreeze = MUArray ty (PrimState prim) -> prim (MutableFreezed (MUArray ty))
forall (prim :: * -> *) ty.
PrimMonad prim =>
MUArray ty (PrimState prim) -> prim (UArray ty)
UV.unsafeFreeze

    mutNew :: CountOf (MutableValue (MUArray ty))
-> prim (MUArray ty (PrimState prim))
mutNew = CountOf (MutableValue (MUArray ty))
-> prim (MUArray ty (PrimState prim))
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
CountOf ty -> prim (MUArray ty (PrimState prim))
MUV.new

    mutUnsafeWrite :: MUArray ty (PrimState prim)
-> MutableKey (MUArray ty) -> MutableValue (MUArray ty) -> prim ()
mutUnsafeWrite = MUArray ty (PrimState prim)
-> MutableKey (MUArray ty) -> MutableValue (MUArray ty) -> prim ()
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
MUArray ty (PrimState prim) -> Offset ty -> ty -> prim ()
MUV.unsafeWrite
    mutUnsafeRead :: MUArray ty (PrimState prim)
-> MutableKey (MUArray ty) -> prim (MutableValue (MUArray ty))
mutUnsafeRead = MUArray ty (PrimState prim)
-> MutableKey (MUArray ty) -> prim (MutableValue (MUArray ty))
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
MUArray ty (PrimState prim) -> Offset ty -> prim ty
MUV.unsafeRead
    mutWrite :: MUArray ty (PrimState prim)
-> MutableKey (MUArray ty) -> MutableValue (MUArray ty) -> prim ()
mutWrite = MUArray ty (PrimState prim)
-> MutableKey (MUArray ty) -> MutableValue (MUArray ty) -> prim ()
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
MUArray ty (PrimState prim) -> Offset ty -> ty -> prim ()
MUV.write
    mutRead :: MUArray ty (PrimState prim)
-> MutableKey (MUArray ty) -> prim (MutableValue (MUArray ty))
mutRead = MUArray ty (PrimState prim)
-> MutableKey (MUArray ty) -> prim (MutableValue (MUArray ty))
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
MUArray ty (PrimState prim) -> Offset ty -> prim ty
MUV.read

instance UV.PrimType ty => MutableCollection (BLK.MutableBlock ty) where
    type MutableFreezed (BLK.MutableBlock ty) = BLK.Block ty
    type MutableKey (BLK.MutableBlock ty) = Offset ty
    type MutableValue (BLK.MutableBlock ty) = ty

    thaw :: MutableFreezed (MutableBlock ty)
-> prim (MutableBlock ty (PrimState prim))
thaw = MutableFreezed (MutableBlock ty)
-> prim (MutableBlock ty (PrimState prim))
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
Block ty -> prim (MutableBlock ty (PrimState prim))
BLK.thaw
    freeze :: MutableBlock ty (PrimState prim)
-> prim (MutableFreezed (MutableBlock ty))
freeze = MutableBlock ty (PrimState prim)
-> prim (MutableFreezed (MutableBlock ty))
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableBlock ty (PrimState prim) -> prim (Block ty)
BLK.freeze
    unsafeThaw :: MutableFreezed (MutableBlock ty)
-> prim (MutableBlock ty (PrimState prim))
unsafeThaw = MutableFreezed (MutableBlock ty)
-> prim (MutableBlock ty (PrimState prim))
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
Block ty -> prim (MutableBlock ty (PrimState prim))
BLK.unsafeThaw
    unsafeFreeze :: MutableBlock ty (PrimState prim)
-> prim (MutableFreezed (MutableBlock ty))
unsafeFreeze = MutableBlock ty (PrimState prim)
-> prim (MutableFreezed (MutableBlock ty))
forall (prim :: * -> *) ty.
PrimMonad prim =>
MutableBlock ty (PrimState prim) -> prim (Block ty)
BLK.unsafeFreeze

    mutNew :: CountOf (MutableValue (MutableBlock ty))
-> prim (MutableBlock ty (PrimState prim))
mutNew = CountOf (MutableValue (MutableBlock ty))
-> prim (MutableBlock ty (PrimState prim))
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
CountOf ty -> prim (MutableBlock ty (PrimState prim))
BLK.new

    mutUnsafeWrite :: MutableBlock ty (PrimState prim)
-> MutableKey (MutableBlock ty)
-> MutableValue (MutableBlock ty)
-> prim ()
mutUnsafeWrite = MutableBlock ty (PrimState prim)
-> MutableKey (MutableBlock ty)
-> MutableValue (MutableBlock ty)
-> prim ()
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
MutableBlock ty (PrimState prim) -> Offset ty -> ty -> prim ()
BLK.unsafeWrite
    mutUnsafeRead :: MutableBlock ty (PrimState prim)
-> MutableKey (MutableBlock ty)
-> prim (MutableValue (MutableBlock ty))
mutUnsafeRead = MutableBlock ty (PrimState prim)
-> MutableKey (MutableBlock ty)
-> prim (MutableValue (MutableBlock ty))
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
MutableBlock ty (PrimState prim) -> Offset ty -> prim ty
BLK.unsafeRead
    mutWrite :: MutableBlock ty (PrimState prim)
-> MutableKey (MutableBlock ty)
-> MutableValue (MutableBlock ty)
-> prim ()
mutWrite = MutableBlock ty (PrimState prim)
-> MutableKey (MutableBlock ty)
-> MutableValue (MutableBlock ty)
-> prim ()
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
MutableBlock ty (PrimState prim) -> Offset ty -> ty -> prim ()
BLK.write
    mutRead :: MutableBlock ty (PrimState prim)
-> MutableKey (MutableBlock ty)
-> prim (MutableValue (MutableBlock ty))
mutRead = MutableBlock ty (PrimState prim)
-> MutableKey (MutableBlock ty)
-> prim (MutableValue (MutableBlock ty))
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
MutableBlock ty (PrimState prim) -> Offset ty -> prim ty
BLK.read

instance MutableCollection (BA.MArray ty) where
    type MutableFreezed (BA.MArray ty) = BA.Array ty
    type MutableKey (BA.MArray ty) = Offset ty
    type MutableValue (BA.MArray ty) = ty

    thaw :: MutableFreezed (MArray ty) -> prim (MArray ty (PrimState prim))
thaw = MutableFreezed (MArray ty) -> prim (MArray ty (PrimState prim))
forall (prim :: * -> *) ty.
PrimMonad prim =>
Array ty -> prim (MArray ty (PrimState prim))
BA.thaw
    freeze :: MArray ty (PrimState prim) -> prim (MutableFreezed (MArray ty))
freeze = MArray ty (PrimState prim) -> prim (MutableFreezed (MArray ty))
forall (prim :: * -> *) ty.
PrimMonad prim =>
MArray ty (PrimState prim) -> prim (Array ty)
BA.freeze
    unsafeThaw :: MutableFreezed (MArray ty) -> prim (MArray ty (PrimState prim))
unsafeThaw = MutableFreezed (MArray ty) -> prim (MArray ty (PrimState prim))
forall (prim :: * -> *) ty.
PrimMonad prim =>
Array ty -> prim (MArray ty (PrimState prim))
BA.unsafeThaw
    unsafeFreeze :: MArray ty (PrimState prim) -> prim (MutableFreezed (MArray ty))
unsafeFreeze = MArray ty (PrimState prim) -> prim (MutableFreezed (MArray ty))
forall (prim :: * -> *) ty.
PrimMonad prim =>
MArray ty (PrimState prim) -> prim (Array ty)
BA.unsafeFreeze

    mutNew :: CountOf (MutableValue (MArray ty))
-> prim (MArray ty (PrimState prim))
mutNew = CountOf (MutableValue (MArray ty))
-> prim (MArray ty (PrimState prim))
forall (prim :: * -> *) ty.
PrimMonad prim =>
CountOf ty -> prim (MArray ty (PrimState prim))
BA.new
    mutUnsafeWrite :: MArray ty (PrimState prim)
-> MutableKey (MArray ty) -> MutableValue (MArray ty) -> prim ()
mutUnsafeWrite = MArray ty (PrimState prim)
-> MutableKey (MArray ty) -> MutableValue (MArray ty) -> prim ()
forall (prim :: * -> *) ty.
PrimMonad prim =>
MArray ty (PrimState prim) -> Offset ty -> ty -> prim ()
BA.unsafeWrite
    mutUnsafeRead :: MArray ty (PrimState prim)
-> MutableKey (MArray ty) -> prim (MutableValue (MArray ty))
mutUnsafeRead = MArray ty (PrimState prim)
-> MutableKey (MArray ty) -> prim (MutableValue (MArray ty))
forall (prim :: * -> *) ty.
PrimMonad prim =>
MArray ty (PrimState prim) -> Offset ty -> prim ty
BA.unsafeRead
    mutWrite :: MArray ty (PrimState prim)
-> MutableKey (MArray ty) -> MutableValue (MArray ty) -> prim ()
mutWrite = MArray ty (PrimState prim)
-> MutableKey (MArray ty) -> MutableValue (MArray ty) -> prim ()
forall (prim :: * -> *) ty.
PrimMonad prim =>
MArray ty (PrimState prim) -> Offset ty -> ty -> prim ()
BA.write
    mutRead :: MArray ty (PrimState prim)
-> MutableKey (MArray ty) -> prim (MutableValue (MArray ty))
mutRead = MArray ty (PrimState prim)
-> MutableKey (MArray ty) -> prim (MutableValue (MArray ty))
forall (prim :: * -> *) ty.
PrimMonad prim =>
MArray ty (PrimState prim) -> Offset ty -> prim ty
BA.read