2-- Module : Streamly.Internal.Data.SmallArray
3-- Copyright : (c) 2019 Composewell Technologies
5-- License : BSD-3-Clause
6-- Maintainer : streamly@composewell.com
7-- Stability : experimental
10{-# OPTIONS_GHC -fno-warn-orphans #-}
13{-# LANGUAGE MagicHash #-}
14{-# LANGUAGE UnboxedTuples #-}
18module Streamly.Internal.Data.SmallArray
44import Prelude hiding (foldr, length, read)
45import Control.DeepSeq (NFData(..))
46import Control.Monad (when)
47import Control.Monad.IO.Class (MonadIO, liftIO)
48import GHC.IO (unsafePerformIO)
49import Data.Functor.Identity (runIdentity)
50import Data.Primitive.SmallArray
52import Streamly.Internal.Data.Unfold.Types (Unfold(..))
53import Streamly.Internal.Data.Fold.Types (Fold(..))
54import Streamly.Streams.StreamK.Type (IsStream)
55import Streamly.Streams.Serial (SerialT)
57import qualified Streamly.Streams.StreamD as D
59{-# NOINLINE bottomElement #-}
61bottomElement = undefined
64length :: SmallArray a -> Int
65length arr = sizeofSmallArray arr
67{-# INLINE_NORMAL toStreamD #-}
68toStreamD :: Monad m => SmallArray a -> D.Stream m a
69toStreamD arr = D.Stream step 0
71 {-# INLINE_LATE step #-}
73 | i == length arr = return D.Stop
76 case indexSmallArray## arr i of
77 (# x #) -> D.Yield x (i + 1)
79{-# INLINE_NORMAL toStreamDRev #-}
80toStreamDRev :: Monad m => SmallArray a -> D.Stream m a
81toStreamDRev arr = D.Stream step (length arr - 1)
83 {-# INLINE_LATE step #-}
85 | i < 0 = return D.Stop
88 case indexSmallArray## arr i of
89 (# x #) -> D.Yield x (i - 1)
91{-# INLINE_NORMAL foldl' #-}
92foldl' :: (b -> a -> b) -> b -> SmallArray a -> b
93foldl' f z arr = runIdentity $ D.foldl' f z $ toStreamD arr
95{-# INLINE_NORMAL foldr #-}
96foldr :: (a -> b -> b) -> b -> SmallArray a -> b
97foldr f z arr = runIdentity $ D.foldr f z $ toStreamD arr
99-- writeN n = S.evertM (fromStreamDN n)
100{-# INLINE_NORMAL writeN #-}
101writeN :: MonadIO m => Int -> Fold m a (SmallArray a)
102writeN limit = Fold step initial extract
105 marr <- liftIO $ newSmallArray limit bottomElement
108 | i == limit = return (marr, i)
110 liftIO $ writeSmallArray marr i x
112 extract (marr, len) = liftIO $ freezeSmallArray marr 0 len
114{-# INLINE_NORMAL fromStreamDN #-}
115fromStreamDN :: MonadIO m => Int -> D.Stream m a -> m (SmallArray a)
116fromStreamDN limit str = do
117 marr <- liftIO $ newSmallArray (max limit 0) bottomElement
120 (\i x -> i `seq` (liftIO $ writeSmallArray marr i x) >> return (i + 1))
123 liftIO $ freezeSmallArray marr 0 i
125{-# INLINABLE fromListN #-}
126fromListN :: Int -> [a] -> SmallArray a
127fromListN n xs = unsafePerformIO $ fromStreamDN n $ D.fromList xs
129instance NFData a => NFData (SmallArray a) where
131 rnf = foldl' (\_ x -> rnf x) ()
133{-# INLINE fromStreamN #-}
134fromStreamN :: MonadIO m => Int -> SerialT m a -> m (SmallArray a)
136 when (n < 0) $ error "fromStreamN: negative write count specified"
137 fromStreamDN n $ D.toStreamD m
139{-# INLINE_EARLY toStream #-}
140toStream :: (Monad m, IsStream t) => SmallArray a -> t m a
141toStream = D.fromStreamD . toStreamD
143{-# INLINE_EARLY toStreamRev #-}
144toStreamRev :: (Monad m, IsStream t) => SmallArray a -> t m a
145toStreamRev = D.fromStreamD . toStreamDRev
148fold :: Monad m => Fold m a b -> SmallArray a -> m b
149fold f arr = D.runFold f (toStreamD arr)
151{-# INLINE streamFold #-}
152streamFold :: Monad m => (SerialT m a -> m b) -> SmallArray a -> m b
153streamFold f arr = f (toStream arr)
155{-# INLINE_NORMAL read #-}
156read :: Monad m => Unfold m (SmallArray a) a
157read = Unfold step inject
159 inject arr = return (arr, 0)
161 | i == length arr = return D.Stop
164 case indexSmallArray## arr i of
165 (# x #) -> D.Yield x (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