1{-# OPTIONS_GHC -fno-warn-orphans #-}
4{-# LANGUAGE MagicHash #-}
5{-# LANGUAGE UnboxedTuples #-}
10-- Module : Streamly.Internal.Data.PrimArray
11-- Copyright : (c) 2019 Composewell Technologies
13-- License : BSD-3-Clause
14-- Maintainer : streamly@composewell.com
15-- Stability : experimental
18module Streamly.Internal.Data.PrimArray
49import Prelude hiding (foldr, length, read)
50import Control.DeepSeq (NFData(..))
51import Control.Monad (when)
52import Control.Monad.IO.Class (liftIO, MonadIO)
53import GHC.IO (unsafePerformIO)
54import GHC.Base (Int(..))
55import Data.Primitive.PrimArray
56import Data.Primitive.Types (Prim(..))
58import Streamly.Internal.Data.Unfold.Types (Unfold(..))
59import Streamly.Internal.Data.Fold.Types (Fold(..))
60import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
61import Streamly.Internal.Data.Stream.Serial (SerialT)
63import qualified Streamly.Internal.Data.Stream.StreamD as D
65{-# INLINE_NORMAL toStreamD #-}
66toStreamD :: (Prim a, Monad m) => PrimArray a -> D.Stream m a
67toStreamD arr = D.Stream step 0
69 {-# INLINE_LATE step #-}
71 | i == sizeofPrimArray arr = return D.Stop
72 step _ i = return $ D.Yield (indexPrimArray arr i) (i + 1)
75length :: Prim a => PrimArray a -> Int
76length arr = sizeofPrimArray arr
78{-# INLINE_NORMAL toStreamDRev #-}
79toStreamDRev :: (Prim a, Monad m) => PrimArray a -> D.Stream m a
80toStreamDRev arr = D.Stream step (sizeofPrimArray arr - 1)
82 {-# INLINE_LATE step #-}
84 | i < 0 = return D.Stop
85 step _ i = return $ D.Yield (indexPrimArray arr i) (i - 1)
87{-# INLINE_NORMAL foldl' #-}
88foldl' :: Prim a => (b -> a -> b) -> b -> PrimArray a -> b
89foldl' = foldlPrimArray'
91{-# INLINE_NORMAL foldr #-}
92foldr :: Prim a => (a -> b -> b) -> b -> PrimArray a -> b
95-- writeN n = S.evertM (fromStreamDN n)
96{-# INLINE_NORMAL writeN #-}
97writeN :: (MonadIO m, Prim a) => Int -> Fold m a (PrimArray a)
98writeN limit = Fold step initial extract
101 marr <- liftIO $ newPrimArray limit
104 | i == limit = return (marr, i)
106 liftIO $ writePrimArray marr i x
108 extract (marr, _) = liftIO $ unsafeFreezePrimArray marr
110{-# INLINE_NORMAL write #-}
111write :: (MonadIO m, Prim a) => Fold m a (PrimArray a)
112write = Fold step initial extract
115 marr <- liftIO $ newPrimArray 0
117 step (marr, i, capacity) x
119 let newCapacity = max (capacity * 2) 1
120 in do newMarr <- liftIO $ resizeMutablePrimArray marr newCapacity
121 liftIO $ writePrimArray newMarr i x
122 return (newMarr, i + 1, newCapacity)
124 liftIO $ writePrimArray marr i x
125 return (marr, i + 1, capacity)
126 extract (marr, len, _) = do liftIO $ shrinkMutablePrimArray marr len
127 liftIO $ unsafeFreezePrimArray marr
129{-# INLINE_NORMAL fromStreamDN #-}
130fromStreamDN :: (MonadIO m, Prim a) => Int -> D.Stream m a -> m (PrimArray a)
131fromStreamDN limit str = do
132 marr <- liftIO $ newPrimArray (max limit 0)
135 (\i x -> i `seq` (liftIO $ writePrimArray marr i x) >> return (i + 1))
138 liftIO $ unsafeFreezePrimArray marr
140{-# INLINE fromStreamD #-}
141fromStreamD :: (MonadIO m, Prim a) => D.Stream m a -> m (PrimArray a)
142fromStreamD str = D.runFold write str
144{-# INLINABLE fromListN #-}
145fromListN :: Prim a => Int -> [a] -> PrimArray a
146fromListN n xs = unsafePerformIO $ fromStreamDN n $ D.fromList xs
148{-# INLINABLE fromList #-}
149fromList :: Prim a => [a] -> PrimArray a
150fromList xs = unsafePerformIO $ fromStreamD $ D.fromList xs
152instance NFData (PrimArray a) where
156{-# INLINE fromStreamN #-}
157fromStreamN :: (MonadIO m, Prim a) => Int -> SerialT m a -> m (PrimArray a)
159 when (n < 0) $ error "fromStreamN: negative write count specified"
160 fromStreamDN n $ D.toStreamD m
162{-# INLINE fromStream #-}
163fromStream :: (MonadIO m, Prim a) => SerialT m a -> m (PrimArray a)
164fromStream m = fromStreamD $ D.toStreamD m
166{-# INLINE_EARLY toStream #-}
167toStream :: (Prim a, Monad m, IsStream t) => PrimArray a -> t m a
168toStream = D.fromStreamD . toStreamD
170{-# INLINE_EARLY toStreamRev #-}
171toStreamRev :: (Prim a, Monad m, IsStream t) => PrimArray a -> t m a
172toStreamRev = D.fromStreamD . toStreamDRev
175fold :: (Prim a, Monad m) => Fold m a b -> PrimArray a -> m b
176fold f arr = D.runFold f (toStreamD arr)
178{-# INLINE streamFold #-}
179streamFold :: (Prim a, Monad m) => (SerialT m a -> m b) -> PrimArray a -> m b
180streamFold f arr = f (toStream arr)
182{-# INLINE_NORMAL read #-}
183read :: (Prim a, Monad m) => Unfold m (PrimArray a) a
184read = Unfold step inject
186 inject arr = return (arr, 0)
188 | i == length arr = return D.Stop
189 step (arr, i) = return $ D.Yield (indexPrimArray arr i) (arr, i + 1)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list