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 :: element -> Update element
write element
element =
  (forall s (vector :: * -> * -> *).
 MVector vector element =>
 vector s element -> Int -> ST s ())
-> Update element
forall element.
(forall s (vector :: * -> * -> *).
 MVector vector element =>
 vector s element -> Int -> ST s ())
-> Update element
Update (\vector s element
mVector Int
offset -> vector (PrimState (ST s)) element -> Int -> element -> ST s ()
forall (m :: * -> *) (v :: * -> * -> *) a.
(PrimMonad m, MVector v a) =>
v (PrimState m) a -> Int -> a -> m ()
A.unsafeWrite vector s element
vector (PrimState (ST s)) element
mVector Int
offset element
element)

{-# INLINE writeMany #-}
writeMany :: B.Vector vector element => vector element -> Update element
writeMany :: vector element -> Update element
writeMany vector element
appendedVector =
  (forall s (vector :: * -> * -> *).
 MVector vector element =>
 vector s element -> Int -> ST s ())
-> Update element
forall element.
(forall s (vector :: * -> * -> *).
 MVector vector element =>
 vector s element -> Int -> ST s ())
-> Update element
Update (\vector s element
mVector Int
offset -> (() -> Int -> element -> ST s ())
-> () -> vector element -> ST s ()
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 -> vector (PrimState (ST s)) element -> Int -> element -> ST s ()
forall (m :: * -> *) (v :: * -> * -> *) a.
(PrimMonad m, MVector v a) =>
v (PrimState m) a -> Int -> a -> m ()
A.unsafeWrite vector s element
vector (PrimState (ST s)) element
mVector (Int -> Int
forall a. a -> a
strict (Int
offset Int -> Int -> Int
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 :: 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 s (vector :: * -> * -> *).
 MVector vector element =>
 vector s element -> Int -> ST s ())
-> Update element
forall element.
(forall s (vector :: * -> * -> *).
 MVector vector element =>
 vector s element -> Int -> ST s ())
-> Update element
Update (\vector s element
mVector Int
offset -> vector s element -> Int -> ST s ()
forall s (vector :: * -> * -> *).
MVector vector element =>
vector s element -> Int -> ST s ()
leftST vector s element
mVector Int
offset ST s () -> ST s () -> ST s ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> vector s element -> Int -> ST s ()
forall s (vector :: * -> * -> *).
MVector vector element =>
vector s element -> Int -> ST s ()
rightST vector s element
mVector (Int -> Int
forall a. a -> a
strict (Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
offset)))

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

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