module VectorBuilder.Core.Update where

import qualified Data.Vector.Generic as B
import qualified Data.Vector.Generic.Mutable as A
import VectorBuilder.Prelude

newtype Update element
  = Update (forall s vector. A.MVector vector element => vector s element -> Int -> ST s ())

{-# INLINE write #-}
write :: element -> Update element
write :: forall element. element -> Update element
write element
element =
  forall element.
(forall s (vector :: * -> * -> *).
 MVector vector element =>
 vector s element -> Int -> ST s ())
-> Update element
Update (\vector s element
mVector Int
offset -> forall (m :: * -> *) (v :: * -> * -> *) a.
(PrimMonad m, MVector v a) =>
v (PrimState m) a -> Int -> a -> m ()
A.unsafeWrite vector s element
mVector Int
offset element
element)

{-# INLINE writeMany #-}
writeMany :: B.Vector vector element => vector element -> Update element
writeMany :: forall (vector :: * -> *) element.
Vector vector element =>
vector element -> Update element
writeMany vector element
appendedVector =
  forall element.
(forall s (vector :: * -> * -> *).
 MVector vector element =>
 vector s element -> Int -> ST s ())
-> Update element
Update (\vector s element
mVector Int
offset -> forall (m :: * -> *) (v :: * -> *) b a.
(Monad m, Vector v b) =>
(a -> Int -> b -> m a) -> a -> v b -> m a
B.ifoldM' (\()
_ Int
index element
element -> forall (m :: * -> *) (v :: * -> * -> *) a.
(PrimMonad m, MVector v a) =>
v (PrimState m) a -> Int -> a -> m ()
A.unsafeWrite vector s element
mVector (forall a. a -> a
strict (Int
offset forall a. Num a => a -> a -> a
+ Int
index)) element
element) () vector element
appendedVector)

{-# INLINE prepend #-}
prepend :: Int -> Update element -> Update element -> Update element
prepend :: forall element.
Int -> Update element -> Update element -> Update element
prepend Int
size (Update forall s (vector :: * -> * -> *).
MVector vector element =>
vector s element -> Int -> ST s ()
leftST) (Update forall s (vector :: * -> * -> *).
MVector vector element =>
vector s element -> Int -> ST s ()
rightST) =
  forall element.
(forall s (vector :: * -> * -> *).
 MVector vector element =>
 vector s element -> Int -> ST s ())
-> Update element
Update (\vector s element
mVector Int
offset -> forall s (vector :: * -> * -> *).
MVector vector element =>
vector s element -> Int -> ST s ()
leftST vector s element
mVector Int
offset forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall s (vector :: * -> * -> *).
MVector vector element =>
vector s element -> Int -> ST s ()
rightST vector s element
mVector (forall a. a -> a
strict (Int
size forall a. Num a => a -> a -> a
+ Int
offset)))

{-# INLINE empty #-}
empty :: Update element
empty :: forall element. Update element
empty =
  forall element.
(forall s (vector :: * -> * -> *).
 MVector vector element =>
 vector s element -> Int -> ST s ())
-> Update element
Update (\vector s element
_ Int
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure ())

{-# INLINE writeFoldable #-}
writeFoldable :: Foldable foldable => foldable element -> Update element
writeFoldable :: forall (foldable :: * -> *) element.
Foldable foldable =>
foldable element -> Update element
writeFoldable foldable element
foldable =
  forall element.
(forall s (vector :: * -> * -> *).
 MVector vector element =>
 vector s element -> Int -> ST s ())
-> Update element
Update (\vector s element
mVector Int
offset -> forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m ()
foldM_ (\Int
index element
element -> forall (m :: * -> *) (v :: * -> * -> *) a.
(PrimMonad m, MVector v a) =>
v (PrimState m) a -> Int -> a -> m ()
A.unsafeWrite vector s element
mVector Int
index element
element forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> forall a. Enum a => a -> a
succ Int
index) Int
offset foldable element
foldable)