66-- | Open process streams with
77-- | [__Node.Process__](https://pursuit.purescript.org/packages/purescript-node-process/docs/Node.Process).
88-- |
9+ -- | All I/O errors will be thrown through the `Aff` `MonadError` class
10+ -- | instance.
11+ -- |
912-- | ## Reading
1013-- |
1114-- | #### Implementation
2124-- | #### Results
2225-- |
2326-- | The result of a reading function may be chunked into more than one `Buffer`.
27+ -- | The `fst` element of the result `Tuple` is an `Array Buffer` of what
28+ -- | was read.
2429-- | To concatenate the result into a single `Buffer`, use
2530-- | `Node.Buffer.concat :: Array Buffer -> Buffer`.
2631-- |
2732-- | ```
28- -- | input :: Buffer <- liftEffect <<< concat =<< readSome stdin
33+ -- | input :: Buffer <- liftEffect <<< concat <<< fst =<< readSome stdin
2934-- | ```
3035-- |
3136-- | To calculate the number of bytes read, use
3237-- | `Node.Buffer.size :: Buffer -> m Int`.
3338-- |
3439-- | ```
35- -- | inputs :: Array Buffer <- readSome stdin
40+ -- | Tuple inputs _ :: Array Buffer <- readSome stdin
3641-- | bytesRead :: Int
3742-- | <- liftEffect $ Array.foldM (\a b -> (a+_) <$> size b) 0 inputs
3843-- | ```
3944-- |
45+ -- | The `snd` element of the result `Tuple` is a `Boolean` flag which
46+ -- | is `true` if the stream has not reached End-Of-File (and also if the stream
47+ -- | has not errored or been destroyed.) If the flag is `false` then
48+ -- | no more bytes will ever be produced by the stream.
49+ -- |
4050-- | #### Canceller argument
4151-- |
4252-- | The reading functions suffixed with underscore take a canceller argument.
4656-- | in the event that the `Aff` is cancelled pass `Node.Stream.destroy`
4757-- | as the canceller.
4858-- |
49- -- | #### EOF
50- -- |
51- -- | There doesn’t seem to be any way to reliably detect when a stream has reached
52- -- | its end? If any one of these reading functions is called on a stream
53- -- | which has already reached its end, then the reading function will never complete.
54- -- |
5559-- | ## Writing
5660-- |
5761-- | #### Implementation
6367-- | function on each of the `Buffer`s,
6468-- | asychronously waiting if there is backpressure from the stream.
6569-- |
66- -- | The writing functions will complete after the data is flushed to the
70+ -- | The writing functions will complete after all the data is flushed to the
6771-- | stream.
6872-- |
6973-- | #### Canceller argument
@@ -92,6 +96,7 @@ import Data.Array as Array
9296import Data.Array.ST as Array.ST
9397import Data.Either (Either (..))
9498import Data.Maybe (Maybe (..))
99+ import Data.Tuple (Tuple (..))
95100import Effect (Effect , untilE )
96101import Effect.Aff (effectCanceler , makeAff )
97102import Effect.Aff.Class (class MonadAff , liftAff )
@@ -100,25 +105,19 @@ import Node.Buffer (Buffer)
100105import Node.Buffer as Buffer
101106import Node.Stream (Readable , Writable )
102107import Node.Stream as Stream
103- import Node.Stream.Aff.Internal (onceDrain , onceEnd , onceError , onceReadable )
108+ import Node.Stream.Aff.Internal (onceDrain , onceEnd , onceError , onceReadable , readable )
104109
105110
106111-- | Wait until there is some data available from the stream, then read it.
107112-- |
108113-- | This function is useful for streams like __stdin__ which never
109114-- | reach End-Of-File.
110115-- |
111- -- | There is no way (?) to reliably detect with *Node.js*
112- -- | when a stream has already reached its end, and if this
113- -- | function is called after the stream has ended then the call will
114- -- | never complete. So we can `readSome` one time and it will complete, but
115- -- | if the stream reached its end then the next call to `readSome`
116- -- | will never complete.
117116readSome
118117 :: forall m r
119118 . MonadAff m
120119 => Readable r
121- -> m (Array Buffer )
120+ -> m (Tuple ( Array Buffer ) Boolean )
122121readSome r = readSome_ r (\_ -> pure unit)
123122
124123-- | __readSome__ with a canceller argument.
@@ -127,26 +126,33 @@ readSome_
127126 . MonadAff m
128127 => Readable r
129128 -> (Readable r -> Effect Unit )
130- -> m (Array Buffer )
129+ -> m (Tuple ( Array Buffer ) Boolean )
131130readSome_ r canceller = liftAff <<< makeAff $ \res -> do
132131 bufs <- liftST $ Array.ST .new
133132
134133 removeError <- onceError r $ res <<< Left
135134
136135 -- try to read right away.
137136 catchException (res <<< Left ) do
138- untilE do
139- Stream .read r Nothing >>= case _ of
140- Nothing -> pure true
141- Just chunk -> do
142- void $ liftST $ Array.ST .push chunk bufs
143- pure false
137+ ifM (readable r)
138+ do
139+ untilE do
140+ Stream .read r Nothing >>= case _ of
141+ Nothing -> pure true
142+ Just chunk -> do
143+ void $ liftST $ Array.ST .push chunk bufs
144+ pure false
145+ do
146+ removeError
147+ res (Right (Tuple [] false ))
148+
144149
145150 ret1 <- liftST $ Array.ST .unsafeFreeze bufs
146151 if Array .length ret1 == 0 then do
147152 -- if we couldn't read anything right away, then wait until the stream is readable.
148153 -- “The 'readable' event will also be emitted once the end of the
149154 -- stream data has been reached but before the 'end' event is emitted.”
155+ -- We already checked the `readable` property so we don't have to check again.
150156 void $ onceReadable r do
151157 catchException (res <<< Left ) do
152158 untilE do
@@ -157,12 +163,14 @@ readSome_ r canceller = liftAff <<< makeAff $ \res -> do
157163 pure false
158164 ret2 <- liftST $ Array.ST .unsafeFreeze bufs
159165 removeError
160- res (Right ret2)
166+ readagain <- readable r
167+ res (Right (Tuple ret2 readagain))
161168
162169 -- return what we read right away
163170 else do
164171 removeError
165- res (Right ret1)
172+ readagain <- readable r
173+ res (Right (Tuple ret1 readagain))
166174
167175 pure $ effectCanceler (canceller r)
168176
@@ -172,7 +180,7 @@ readAll
172180 :: forall m r
173181 . MonadAff m
174182 => Readable r
175- -> m (Array Buffer )
183+ -> m (Tuple ( Array Buffer ) Boolean )
176184readAll r = readAll_ r (\_ -> pure unit)
177185
178186-- | __readAll__ with a canceller argument.
@@ -181,7 +189,7 @@ readAll_
181189 . MonadAff m
182190 => Readable r
183191 -> (Readable r -> Effect Unit )
184- -> m (Array Buffer )
192+ -> m (Tuple ( Array Buffer ) Boolean )
185193readAll_ r canceller = liftAff <<< makeAff $ \res -> do
186194 bufs <- liftST $ Array.ST .new
187195
@@ -190,7 +198,7 @@ readAll_ r canceller = liftAff <<< makeAff $ \res -> do
190198 removeEnd <- onceEnd r do
191199 removeError
192200 ret <- liftST $ Array.ST .unsafeFreeze bufs
193- res (Right ret)
201+ res (Right ( Tuple ret false ) )
194202
195203 let
196204 cleanupRethrow err = do
@@ -200,12 +208,18 @@ readAll_ r canceller = liftAff <<< makeAff $ \res -> do
200208
201209 -- try to read right away.
202210 catchException cleanupRethrow do
203- untilE do
204- Stream .read r Nothing >>= case _ of
205- Nothing -> pure true
206- Just chunk -> do
207- void $ liftST $ Array.ST .push chunk bufs
208- pure false
211+ ifM (readable r)
212+ do
213+ untilE do
214+ Stream .read r Nothing >>= case _ of
215+ Nothing -> pure true
216+ Just chunk -> do
217+ void $ liftST $ Array.ST .push chunk bufs
218+ pure false
219+ do
220+ removeError
221+ removeEnd
222+ res (Right (Tuple [] false ))
209223
210224 -- then wait for the stream to be readable until the stream has ended.
211225 let
@@ -238,7 +252,7 @@ readN
238252 . MonadAff m
239253 => Readable r
240254 -> Int
241- -> m (Array Buffer )
255+ -> m (Tuple ( Array Buffer ) Boolean )
242256readN r n = readN_ r (\_ -> pure unit) n
243257
244258-- | __readN__ with a canceller argument.
@@ -248,7 +262,7 @@ readN_
248262 => Readable r
249263 -> (Readable r -> Effect Unit )
250264 -> Int
251- -> m (Array Buffer )
265+ -> m (Tuple ( Array Buffer ) Boolean )
252266readN_ r canceller n = liftAff <<< makeAff $ \res -> do
253267 redRef <- liftST $ STRef .new 0
254268 bufs <- liftST $ Array.ST .new
@@ -261,7 +275,7 @@ readN_ r canceller n = liftAff <<< makeAff $ \res -> do
261275 removeEnd <- onceEnd r do
262276 removeError
263277 ret <- liftST $ Array.ST .unsafeFreeze bufs
264- res (Right ret)
278+ res (Right ( Tuple ret false ) )
265279
266280 let
267281 cleanupRethrow err = do
@@ -293,12 +307,19 @@ readN_ r canceller n = liftAff <<< makeAff $ \res -> do
293307 removeError
294308 removeEnd
295309 ret <- liftST $ Array.ST .unsafeFreeze bufs
296- res (Right ret)
310+ readagain <- readable r
311+ res (Right (Tuple ret readagain))
297312 else
298313 continuation unit
299314
300315 -- try to read right away.
301- tryToRead (\_ -> pure unit)
316+ ifM (readable r)
317+ do
318+ tryToRead (\_ -> pure unit)
319+ do
320+ removeError
321+ removeEnd
322+ res (Right (Tuple [] false ))
302323
303324 -- if there were not enough bytes right away, then wait for bytes to come in.
304325 let
0 commit comments