-- Adapted from `grow-vector` as the package seems unmaintained
-- Module defines mutable vector that can grow in size automatically when an user
-- adds new elements at the end of vector.
--
-- We reallocate vector with 1.5x length to get amortized append.
{- HLINT ignore "Use camelCase" -}
module Mischief.ECS.Vec
  ( Vec (..),
    IOVec,

    -- * Quering info about vector
    length,
    null,
    capacity,

    -- * Creation
    new,
    newSized,

    -- * Quering subvectors
    slice,

    -- * Converting to immutable
    thaw,
    freeze,
    toList,

    -- * Capacity maninuplation
    ensure,
    ensureAppend,

    -- * Accessing individual elements
    read,
    write,
    unsafeRead,
    unsafeWrite,

    -- * Appending to vector
    pushBack,
    unsafePushBack,

    -- * modify an element
    modify,
    modify_,
    modifyM,
    modifyM_,

    -- * general utilities
    swap,
    tap,
    shrink,

    -- * O(1) amortized swap backed operations
    takeSwap,
    removeSwap,

    -- * cloning, very naive approach
    clone,
  )
where

import Control.Monad
import Control.Monad.Primitive
import Data.Foldable (for_)
import Data.Primitive.MutVar
import Data.Vector (Vector)
import Data.Vector qualified as Vector
import Data.Vector.Mutable (MVector)
import Data.Vector.Mutable qualified as MVector
import GHC.Generics
import GHC.Stack (HasCallStack)
import Prelude hiding (length, null, read)

-- | Normal rust-like vector with buffer (the MVector) + len (the len field) + cap (the `buffer` length)
data Vec s a = Vec
  { forall s a. Vec s a -> MutVar s (MVector s a)
buffer :: !(MutVar s (MVector s a)),
    forall s a. Vec s a -> MutVar s Int
len :: !(MutVar s Int)
  }
  deriving ((forall x. Vec s a -> Rep (Vec s a) x)
-> (forall x. Rep (Vec s a) x -> Vec s a) -> Generic (Vec s a)
forall x. Rep (Vec s a) x -> Vec s a
forall x. Vec s a -> Rep (Vec s a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall s a x. Rep (Vec s a) x -> Vec s a
forall s a x. Vec s a -> Rep (Vec s a) x
$cfrom :: forall s a x. Vec s a -> Rep (Vec s a) x
from :: forall x. Vec s a -> Rep (Vec s a) x
$cto :: forall s a x. Rep (Vec s a) x -> Vec s a
to :: forall x. Rep (Vec s a) x -> Vec s a
Generic)

type IOVec a = Vec RealWorld a

-- | Return current capacity of the vector (amount of elements that it can fit without realloc)
capacity :: (PrimMonad m) => Vec (PrimState m) a -> m Int
capacity :: forall (m :: * -> *) a. PrimMonad m => Vec (PrimState m) a -> m Int
capacity Vec (PrimState m) a
v =
  MVector (PrimState m) a -> Int
forall s a. MVector s a -> Int
MVector.length (MVector (PrimState m) a -> Int)
-> m (MVector (PrimState m) a) -> m Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MutVar (PrimState m) (MVector (PrimState m) a)
-> m (MVector (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar Vec (PrimState m) a
v.buffer
{-# INLINE capacity #-}

-- | Return current amount of elements in the vector
length :: (PrimMonad m) => Vec (PrimState m) a -> m Int
length :: forall (m :: * -> *) a. PrimMonad m => Vec (PrimState m) a -> m Int
length Vec (PrimState m) a
v = MutVar (PrimState m) Int -> m Int
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar Vec (PrimState m) a
v.len
{-# INLINE length #-}

-- | Return 'True' if there is no elements inside the vector
null :: (PrimMonad m) => Vec (PrimState m) a -> m Bool
null :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> m Bool
null Vec (PrimState m) a
v = (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0) (Int -> Bool) -> m Int -> m Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vec (PrimState m) a -> m Int
forall (m :: * -> *) a. PrimMonad m => Vec (PrimState m) a -> m Int
length Vec (PrimState m) a
v

-- | Allocation of new growable vector with given capacity.
new :: (PrimMonad m) => Int -> m (Vec (PrimState m) a)
new :: forall (m :: * -> *) a.
PrimMonad m =>
Int -> m (Vec (PrimState m) a)
new = Int -> Int -> m (Vec (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> Int -> m (Vec (PrimState m) a)
newSized Int
0
{-# INLINE new #-}

-- | Allocation of new growable vector with given filled size and capacity.
-- Elements is not initialized. Capacity must be greater than filled size.
newSized :: (PrimMonad m) => Int -> Int -> m (Vec (PrimState m) a)
newSized :: forall (m :: * -> *) a.
PrimMonad m =>
Int -> Int -> m (Vec (PrimState m) a)
newSized Int
n Int
cap = do
  buffer <- Int -> m (MVector (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> m (MVector (PrimState m) a)
MVector.new Int
cap
  buffer <- newMutVar buffer
  len <- newMutVar n
  pure Vec {buffer, len}
{-# INLINEABLE newSized #-}

-- | Yield a part of mutable vector without copying it. The vector must contain at least i+n elements.
slice ::
  (PrimMonad m) =>
  -- | i starting index
  Int ->
  -- | n number of elements
  Int ->
  Vec (PrimState m) a ->
  m (Vec (PrimState m) a)
slice :: forall (m :: * -> *) a.
PrimMonad m =>
Int -> Int -> Vec (PrimState m) a -> m (Vec (PrimState m) a)
slice Int
i Int
n Vec (PrimState m) a
v = do
  len <- Int -> m (MutVar (PrimState m) Int)
forall (m :: * -> *) a.
PrimMonad m =>
a -> m (MutVar (PrimState m) a)
newMutVar Int
n
  mv <- readMutVar v.buffer
  buffer <- newMutVar $! MVector.slice i n mv
  pure $! Vec {len, buffer}
{-# INLINEABLE slice #-}

-- | Convert immutable vector to grow mutable version. Doesn't allocate additonal memory for appending,
-- use 'ensure' to add capacity to the vector.
thaw ::
  (PrimMonad m) =>
  Vector a ->
  m (Vec (PrimState m) a)
thaw :: forall (m :: * -> *) a.
PrimMonad m =>
Vector a -> m (Vec (PrimState m) a)
thaw Vector a
u = do
  buffer <- MVector (PrimState m) a
-> m (MutVar (PrimState m) (MVector (PrimState m) a))
forall (m :: * -> *) a.
PrimMonad m =>
a -> m (MutVar (PrimState m) a)
newMutVar (MVector (PrimState m) a
 -> m (MutVar (PrimState m) (MVector (PrimState m) a)))
-> m (MVector (PrimState m) a)
-> m (MutVar (PrimState m) (MVector (PrimState m) a))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Vector a -> m (MVector (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
Vector a -> m (MVector (PrimState m) a)
Vector.thaw Vector a
u
  len <- newMutVar $! Vector.length u
  pure Vec {buffer, len}
{-# INLINEABLE thaw #-}

-- | Freezing growable vector. It will contain only actual elements of the vector not including capacity
-- space, but you should call 'U.force' on resulting vector to not hold the allocated capacity of original
-- vector in memory.
freeze ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  m (Vector a)
freeze :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> m (Vector a)
freeze Vec (PrimState m) a
v = do
  n <- Vec (PrimState m) a -> m Int
forall (m :: * -> *) a. PrimMonad m => Vec (PrimState m) a -> m Int
length Vec (PrimState m) a
v
  mv <- readMutVar v.buffer
  Vector.freeze $ MVector.take n mv
{-# INLINEABLE freeze #-}

toList ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  m [a]
toList :: forall (m :: * -> *) a. PrimMonad m => Vec (PrimState m) a -> m [a]
toList Vec (PrimState m) a
vec = Vector a -> [a]
forall a. Vector a -> [a]
Vector.toList (Vector a -> [a]) -> m (Vector a) -> m [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vec (PrimState m) a -> m (Vector a)
forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> m (Vector a)
freeze Vec (PrimState m) a
vec

ensure_not_oob ::
  (HasCallStack, PrimMonad m) =>
  String ->
  -- | the name of the function
  Int ->
  -- | The element we want to check
  Vec (PrimState m) a ->
  -- | The length of the vec
  m ()
ensure_not_oob :: forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
String -> Int -> Vec (PrimState m) a -> m ()
ensure_not_oob String
fname Int
i Vec (PrimState m) a
vec = do
  len <- Vec (PrimState m) a -> m Int
forall (m :: * -> *) a. PrimMonad m => Vec (PrimState m) a -> m Int
length Vec (PrimState m) a
vec
  when (i < 0 || i >= len) $ do
    error $ mconcat [fname, ": index ", show i, " is out bounds ", show len]

-- | Ensure that grow vector has at least given capacity possibly with reallocation.
ensure ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  Int ->
  m ()
ensure :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> m ()
ensure Vec (PrimState m) a
v Int
cap = do
  current_cap <- Vec (PrimState m) a -> m Int
forall (m :: * -> *) a. PrimMonad m => Vec (PrimState m) a -> m Int
capacity Vec (PrimState m) a
v
  unless (current_cap >= cap) $ do
    buffer <- readMutVar v.buffer
    grown <- MVector.grow buffer (cap - current_cap)
    writeMutVar v.buffer grown
{-# INLINEABLE ensure #-}

-- | Ensure that grow vector has enough space for additonal n elements.
-- We grow vector by 1.5 factor or by required elements count * 1.5.
ensureAppend ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  -- | Additional n elements
  Int ->
  m ()
ensureAppend :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> m ()
ensureAppend Vec (PrimState m) a
vec Int
i = do
  len <- Vec (PrimState m) a -> m Int
forall (m :: * -> *) a. PrimMonad m => Vec (PrimState m) a -> m Int
length Vec (PrimState m) a
vec
  buf <- readMutVar vec.buffer
  let cap = MVector (PrimState m) a -> Int
forall s a. MVector s a -> Int
MVector.length MVector (PrimState m) a
buf
  unless (cap >= len + i) $ do
    -- ugly as shit code would like to fix
    let newCap = Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Double -> Int) -> Double -> Int
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double
forall a. Ord a => a -> a -> a
max (Double
growFactor Double -> Double -> Double
forall a. Num a => a -> a -> a
* Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
cap) (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
cap Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
growFactor Double -> Double -> Double
forall a. Num a => a -> a -> a
* Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
cap))
    new_buf <- MVector.grow buf (newCap - cap)
    writeMutVar vec.buffer new_buf
  where
    growFactor :: Double
    growFactor :: Double
growFactor = Double
1.5
{-# INLINEABLE ensureAppend #-}

-- | Read element from vector at given index.
read ::
  (HasCallStack, PrimMonad m) =>
  Vec (PrimState m) a ->
  -- | Index of element. Must be in [0 .. length) range
  Int ->
  m a
read :: forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
Vec (PrimState m) a -> Int -> m a
read Vec (PrimState m) a
vec Int
i = do
  String -> Int -> Vec (PrimState m) a -> m ()
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
String -> Int -> Vec (PrimState m) a -> m ()
ensure_not_oob String
"Vec.read" Int
i Vec (PrimState m) a
vec
  buf <- MutVar (PrimState m) (MVector (PrimState m) a)
-> m (MVector (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar Vec (PrimState m) a
vec.buffer
  MVector.unsafeRead buf i
{-# INLINEABLE read #-}

-- | Read element from vector at given index, without checking whether the index is inbounds
unsafeRead ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  -- | Index of element. Must be in [0 .. length) range
  Int ->
  m a
unsafeRead :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> m a
unsafeRead Vec (PrimState m) a
vec Int
i = do
  buf <- MutVar (PrimState m) (MVector (PrimState m) a)
-> m (MVector (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar Vec (PrimState m) a
vec.buffer
  MVector.unsafeRead buf i
{-# INLINEABLE unsafeRead #-}

-- | Write down element in the vector at given index.
write ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  -- | Index of element. Must be in [0 .. length) range
  Int ->
  a ->
  m ()
write :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> a -> m ()
write Vec (PrimState m) a
vec Int
i a
value = do
  String -> Int -> Vec (PrimState m) a -> m ()
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
String -> Int -> Vec (PrimState m) a -> m ()
ensure_not_oob String
"Vec.write" Int
i Vec (PrimState m) a
vec
  buf <- MutVar (PrimState m) (MVector (PrimState m) a)
-> m (MVector (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar Vec (PrimState m) a
vec.buffer
  MVector.unsafeWrite buf i value
{-# INLINEABLE write #-}

-- | Write down element in the vector at given index.
unsafeWrite ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  -- | Index of element. Must be in [0 .. length) range
  Int ->
  a ->
  m ()
unsafeWrite :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> a -> m ()
unsafeWrite Vec (PrimState m) a
vec Int
i a
value = do
  buf <- MutVar (PrimState m) (MVector (PrimState m) a)
-> m (MVector (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar Vec (PrimState m) a
vec.buffer
  MVector.unsafeWrite buf i value
{-# INLINEABLE unsafeWrite #-}

modify ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  Int ->
  (a -> a) ->
  m a
modify :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> (a -> a) -> m a
modify Vec (PrimState m) a
vec Int
i a -> a
f = do
  String -> Int -> Vec (PrimState m) a -> m ()
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
String -> Int -> Vec (PrimState m) a -> m ()
ensure_not_oob String
"Vec.modify" Int
i Vec (PrimState m) a
vec
  old_val <- Vec (PrimState m) a -> Int -> m a
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
Vec (PrimState m) a -> Int -> m a
read Vec (PrimState m) a
vec Int
i
  write vec i (f old_val)
  pure old_val
{-# INLINEABLE modify #-}

modify_ ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  Int ->
  (a -> a) ->
  m ()
modify_ :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> (a -> a) -> m ()
modify_ Vec (PrimState m) a
vec Int
i a -> a
f = do
  String -> Int -> Vec (PrimState m) a -> m ()
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
String -> Int -> Vec (PrimState m) a -> m ()
ensure_not_oob String
"Vec.modify_" Int
i Vec (PrimState m) a
vec
  old_val <- Vec (PrimState m) a -> Int -> m a
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
Vec (PrimState m) a -> Int -> m a
read Vec (PrimState m) a
vec Int
i
  write vec i (f old_val)
{-# INLINEABLE modify_ #-}

modifyM ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  Int ->
  (a -> m a) ->
  m a
modifyM :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> (a -> m a) -> m a
modifyM Vec (PrimState m) a
vec Int
i a -> m a
f = do
  String -> Int -> Vec (PrimState m) a -> m ()
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
String -> Int -> Vec (PrimState m) a -> m ()
ensure_not_oob String
"Vec.modifyM" Int
i Vec (PrimState m) a
vec
  old_val <- Vec (PrimState m) a -> Int -> m a
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
Vec (PrimState m) a -> Int -> m a
read Vec (PrimState m) a
vec Int
i
  write vec i =<< f old_val
  pure old_val
{-# INLINEABLE modifyM #-}

modifyM_ ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  Int ->
  (a -> m a) ->
  m ()
modifyM_ :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> (a -> m a) -> m ()
modifyM_ Vec (PrimState m) a
vec Int
i a -> m a
f = do
  String -> Int -> Vec (PrimState m) a -> m ()
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
String -> Int -> Vec (PrimState m) a -> m ()
ensure_not_oob String
"Vec.modifyM_" Int
i Vec (PrimState m) a
vec
  old_val <- Vec (PrimState m) a -> Int -> m a
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
Vec (PrimState m) a -> Int -> m a
read Vec (PrimState m) a
vec Int
i
  write vec i =<< f old_val
{-# INLINEABLE modifyM_ #-}

tap ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  Int ->
  (a -> m ()) ->
  m ()
tap :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> (a -> m ()) -> m ()
tap Vec (PrimState m) a
vec Int
i a -> m ()
act = do
  String -> Int -> Vec (PrimState m) a -> m ()
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
String -> Int -> Vec (PrimState m) a -> m ()
ensure_not_oob String
"Vec.tap" Int
i Vec (PrimState m) a
vec
  a -> m ()
act (a -> m ()) -> m a -> m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Vec (PrimState m) a -> Int -> m a
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
Vec (PrimState m) a -> Int -> m a
read Vec (PrimState m) a
vec Int
i
{-# INLINE tap #-}

-- | O(1) amortized appending to vector
pushBack ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  a ->
  m ()
pushBack :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> a -> m ()
pushBack Vec (PrimState m) a
vec a
value = do
  Vec (PrimState m) a -> Int -> m ()
forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> m ()
ensureAppend Vec (PrimState m) a
vec Int
1
  Vec (PrimState m) a -> a -> m ()
forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> a -> m ()
unsafePushBack Vec (PrimState m) a
vec a
value
{-# INLINEABLE pushBack #-}

-- | O(1) amortized appending to vector. Doesn't reallocate vector, so
-- there must by capacity - length >= 1.
unsafePushBack ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  a ->
  m ()
unsafePushBack :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> a -> m ()
unsafePushBack Vec (PrimState m) a
vec a
a = do
  len <- Vec (PrimState m) a -> m Int
forall (m :: * -> *) a. PrimMonad m => Vec (PrimState m) a -> m Int
length Vec (PrimState m) a
vec
  buf <- readMutVar vec.buffer
  MVector.write buf len a
  writeMutVar vec.len (len + 1)
{-# INLINEABLE unsafePushBack #-}

swap ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  Int ->
  -- | index of element #1 to swap
  Int ->
  -- | index of element #2 to swap
  m ()
swap :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> Int -> m ()
swap Vec (PrimState m) a
vec Int
i Int
j = do
  Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
j) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
    String -> Int -> Vec (PrimState m) a -> m ()
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
String -> Int -> Vec (PrimState m) a -> m ()
ensure_not_oob String
"Vec.swap" Int
i Vec (PrimState m) a
vec
    String -> Int -> Vec (PrimState m) a -> m ()
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
String -> Int -> Vec (PrimState m) a -> m ()
ensure_not_oob String
"Vec.swap" Int
j Vec (PrimState m) a
vec
    buffer <- MutVar (PrimState m) (MVector (PrimState m) a)
-> m (MVector (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar Vec (PrimState m) a
vec.buffer
    MVector.swap buffer i j

shrink ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  Int ->
  m ()
shrink :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> m ()
shrink Vec (PrimState m) a
vec Int
amount = do
  old_len <- Vec (PrimState m) a -> m Int
forall (m :: * -> *) a. PrimMonad m => Vec (PrimState m) a -> m Int
length Vec (PrimState m) a
vec
  writeMutVar vec.len (old_len - amount)

takeSwap ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  Int ->
  m a
takeSwap :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> m a
takeSwap Vec (PrimState m) a
vec Int
i = do
  value <- Vec (PrimState m) a -> Int -> m a
forall (m :: * -> *) a.
(HasCallStack, PrimMonad m) =>
Vec (PrimState m) a -> Int -> m a
read Vec (PrimState m) a
vec Int
i
  removeSwap vec i
  pure value

removeSwap ::
  (PrimMonad m) =>
  Vec (PrimState m) a ->
  -- | index of element to remove
  Int ->
  m ()
removeSwap :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> Int -> m ()
removeSwap Vec (PrimState m) a
vec Int
i = do
  len <- Vec (PrimState m) a -> m Int
forall (m :: * -> *) a. PrimMonad m => Vec (PrimState m) a -> m Int
length Vec (PrimState m) a
vec
  swap vec i (len - 1)
  shrink vec 1

clone :: (PrimMonad m) => Vec (PrimState m) a -> m (Vec (PrimState m) a)
clone :: forall (m :: * -> *) a.
PrimMonad m =>
Vec (PrimState m) a -> m (Vec (PrimState m) a)
clone Vec (PrimState m) a
vec = do
  list <- Vec (PrimState m) a -> m [a]
forall (m :: * -> *) a. PrimMonad m => Vec (PrimState m) a -> m [a]
toList Vec (PrimState m) a
vec
  len <- length vec
  newVec <- new len
  for_ list $ pushBack newVec
  return newVec