1{-# OPTIONS_GHC -fno-warn-orphans #-}
4{-# LANGUAGE MagicHash #-}
5{-# LANGUAGE UnboxedTuples #-}
10-- Module : Streamly.Internal.Data.Prim.Array
11-- Copyright : (c) 2019 Composewell Technologies
13-- License : BSD-3-Clause
14-- Maintainer : streamly@composewell.com
15-- Stability : experimental
18module Streamly.Internal.Data.Prim.Array
51import Prelude hiding (foldr, length, read)
52import Control.DeepSeq (NFData(..))
53import Control.Monad (when)
54import Control.Monad.IO.Class (liftIO, MonadIO)
55import GHC.IO (unsafePerformIO)
56import Data.Primitive.PrimArray
57import Data.Primitive.Types (Prim(..))
59import Streamly.Internal.Data.Unfold.Types (Unfold(..))
60import Streamly.Internal.Data.Fold.Types (Fold(..))
61import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
62import Streamly.Internal.Data.Stream.Serial (SerialT)
64import qualified Streamly.Internal.Data.Stream.StreamD as D
66{-# INLINE_NORMAL toStreamD #-}
67toStreamD :: (Prim a, Monad m) => PrimArray a -> D.Stream m a
68toStreamD arr = D.Stream step 0
70 {-# INLINE_LATE step #-}
72 | i == sizeofPrimArray arr = return D.Stop
73 step _ i = return $ D.Yield (indexPrimArray arr i) (i + 1)
76length :: Prim a => PrimArray a -> Int
77length arr = sizeofPrimArray arr
79{-# INLINE_NORMAL toStreamDRev #-}
80toStreamDRev :: (Prim a, Monad m) => PrimArray a -> D.Stream m a
81toStreamDRev arr = D.Stream step (sizeofPrimArray arr - 1)
83 {-# INLINE_LATE step #-}
85 | i < 0 = return D.Stop
86 step _ i = return $ D.Yield (indexPrimArray arr i) (i - 1)
88{-# INLINE_NORMAL foldl' #-}
89foldl' :: Prim a => (b -> a -> b) -> b -> PrimArray a -> b
90foldl' = foldlPrimArray'
92{-# INLINE_NORMAL foldr #-}
93foldr :: Prim a => (a -> b -> b) -> b -> PrimArray a -> b
96-- writeN n = S.evertM (fromStreamDN n)
97{-# INLINE_NORMAL writeN #-}
98writeN :: (MonadIO m, Prim a) => Int -> Fold m a (PrimArray a)
99writeN limit = Fold step initial extract
102 marr <- liftIO $ newPrimArray limit
105 | i == limit = return (marr, i)
107 liftIO $ writePrimArray marr i x
109 extract (marr, _) = liftIO $ unsafeFreezePrimArray marr
111{-# INLINE_NORMAL write #-}
112write :: (MonadIO m, Prim a) => Fold m a (PrimArray a)
113write = Fold step initial extract
116 marr <- liftIO $ newPrimArray 0
118 step (marr, i, capacity) x
120 let newCapacity = max (capacity * 2) 1
121 in do newMarr <- liftIO $ resizeMutablePrimArray marr newCapacity
122 liftIO $ writePrimArray newMarr i x
123 return (newMarr, i + 1, newCapacity)
125 liftIO $ writePrimArray marr i x
126 return (marr, i + 1, capacity)
127 extract (marr, len, _) = do liftIO $ shrinkMutablePrimArray marr len
128 liftIO $ unsafeFreezePrimArray marr
130{-# INLINE_NORMAL fromStreamDN #-}
131fromStreamDN :: (MonadIO m, Prim a) => Int -> D.Stream m a -> m (PrimArray a)
132fromStreamDN limit str = do
133 marr <- liftIO $ newPrimArray (max limit 0)
136 (\i x -> i `seq` (liftIO $ writePrimArray marr i x) >> return (i + 1))
139 liftIO $ unsafeFreezePrimArray marr
141{-# INLINE fromStreamD #-}
142fromStreamD :: (MonadIO m, Prim a) => D.Stream m a -> m (PrimArray a)
143fromStreamD str = D.runFold write str
145{-# INLINABLE fromListN #-}
146fromListN :: Prim a => Int -> [a] -> PrimArray a
147fromListN n xs = unsafePerformIO $ fromStreamDN n $ D.fromList xs
149{-# INLINABLE fromList #-}
150fromList :: Prim a => [a] -> PrimArray a
151fromList xs = unsafePerformIO $ fromStreamD $ D.fromList xs
153instance Prim a => NFData (PrimArray a) where
155 rnf = foldl' (\_ _ -> ()) ()
157{-# INLINE fromStreamN #-}
158fromStreamN :: (MonadIO m, Prim a) => Int -> SerialT m a -> m (PrimArray a)
160 when (n < 0) $ error "fromStreamN: negative write count specified"
161 fromStreamDN n $ D.toStreamD m
163{-# INLINE fromStream #-}
164fromStream :: (MonadIO m, Prim a) => SerialT m a -> m (PrimArray a)
165fromStream m = fromStreamD $ D.toStreamD m
167{-# INLINE_EARLY toStream #-}
168toStream :: (Prim a, Monad m, IsStream t) => PrimArray a -> t m a
169toStream = D.fromStreamD . toStreamD
171{-# INLINE_EARLY toStreamRev #-}
172toStreamRev :: (Prim a, Monad m, IsStream t) => PrimArray a -> t m a
173toStreamRev = D.fromStreamD . toStreamDRev
176fold :: (Prim a, Monad m) => Fold m a b -> PrimArray a -> m b
177fold f arr = D.runFold f (toStreamD arr)
179{-# INLINE streamFold #-}
180streamFold :: (Prim a, Monad m) => (SerialT m a -> m b) -> PrimArray a -> m b
181streamFold f arr = f (toStream arr)
183{-# INLINE_NORMAL read #-}
184read :: (Prim a, Monad m) => Unfold m (PrimArray a) a
185read = Unfold step inject
187 inject arr = return (arr, 0)
189 | i == length arr = return D.Stop
190 step (arr, i) = return $ D.Yield (indexPrimArray arr i) (arr, i + 1)
192{-# INLINE_NORMAL readSlice #-}
193readSlice :: (Prim a, Monad m) => Int -> Int -> Unfold m (PrimArray a) a
194readSlice off len = Unfold step inject
196 inject arr = return (arr, off)
198 | i == min (off + len) (length arr) = return D.Stop
199 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