pvector-0.1.0.0: src/Data/Vector/Persistent/Internal/Buffer.hs
module Data.Vector.Persistent.Internal.Buffer where
import Control.Monad.Primitive
import Data.Primitive.SmallArray
import Data.Vector.Persistent.Internal.Array (shrinkSmallMutableArray_)
import Prelude hiding (length)
data Buffer s a = Buffer
{ offset :: !Int,
marr :: !(SmallMutableArray s a)
}
new :: (PrimMonad m, s ~ PrimState m) => m (Buffer s a)
new = do
marr <- newSmallArray 0 undefinedElem
pure Buffer {offset = 0, marr}
{-# INLINE new #-}
newWithCapacity :: (PrimMonad m, s ~ PrimState m) => Int -> m (Buffer s a)
newWithCapacity cap = do
marr <- newSmallArray cap undefinedElem
pure Buffer {offset = 0, marr}
{-# INLINE newWithCapacity #-}
push :: (PrimMonad m, s ~ PrimState m) => a -> Buffer s a -> m (Buffer s a)
push a buffer = do
buffer' <-
if length buffer == capacity buffer
then resize buffer
else pure buffer
writeSmallArray (marr buffer') (length buffer) a
pure buffer' {offset = offset buffer' + 1}
{-# INLINE push #-}
read :: (PrimMonad m, s ~ PrimState m) => Int -> Buffer s a -> m a
read i Buffer {marr} = readSmallArray marr i
{-# INLINE read #-}
write :: (PrimMonad m, s ~ PrimState m) => Int -> a -> Buffer s a -> m ()
write i a Buffer {marr} = writeSmallArray marr i a
{-# INLINE write #-}
clear :: Buffer s a -> Buffer s a
clear = shrink 0
{-# INLINE clear #-}
shrink :: Int -> Buffer s a -> Buffer s a
shrink i buffer = buffer {offset = i}
{-# INLINE shrink #-}
unsafeShrink :: (PrimMonad m, s ~ PrimState m) => Int -> Buffer s a -> m (Buffer s a)
unsafeShrink i Buffer {marr} = do
marr <- shrinkSmallMutableArray_ marr i
pure Buffer {marr, offset = i}
{-# INLINE unsafeShrink #-}
capacity :: Buffer s a -> Int
capacity Buffer {marr} = sizeofSmallMutableArray marr
{-# INLINE capacity #-}
null :: Buffer s a -> Bool
null = (0 ==) . length
length :: Buffer s a -> Int
length = offset
{-# INLINE length #-}
undefinedElem :: forall a. a
undefinedElem = error "undefined element"
{-# NOINLINE undefinedElem #-}
resize :: (PrimMonad m, s ~ PrimState m) => Buffer s a -> m (Buffer s a)
resize buffer = do
if capacity buffer == 0
then grow 32 buffer
else grow (capacity buffer) buffer
{-# INLINE resize #-}
grow :: (PrimMonad m, s ~ PrimState m) => Int -> Buffer s a -> m (Buffer s a)
grow more buffer@Buffer {marr, offset} = do
marr' <- newSmallArray (sizeofSmallMutableArray marr + more) undefinedElem
copySmallMutableArray marr' 0 marr 0 offset
pure buffer {marr = marr'}
{-# INLINE grow #-}
freeze :: (PrimMonad m, s ~ PrimState m) => Buffer s a -> m (SmallArray a)
freeze Buffer {marr, offset} = freezeSmallArray marr 0 offset
{-# INLINE freeze #-}
unsafeFreeze :: (PrimMonad m, s ~ PrimState m) => Buffer s a -> m (SmallArray a)
unsafeFreeze Buffer {marr, offset} = do
marr <- shrinkSmallMutableArray_ marr offset
unsafeFreezeSmallArray marr
{-# INLINE unsafeFreeze #-}