on master help sign in
Split stdio ops into a Console.Stdio module

Change the FileSystem.Handle from* APIs to put* Mutable write APIs would use a "put" prefix to make the name more intuitive.

commit6132eb3acbdce1c4982088d88b1be78ce46de107 authorHarendra Kumar <harendra@composewell.com> dateThu 22 Apr 2021, 18:24 (5 years ago) parent0cfc423
8 files changed+355−98
benchmark/Streamly/Benchmark/FileSystem/Handle/ReadWrite.hs+3−3 benchmark/Streamly/Benchmark/Prelude/Serial/Exceptions.hs+2−2 design/container-api.md+65 src/Streamly/Console/Stdio.hs+31 src/Streamly/Internal/Console/Stdio.hs+229 src/Streamly/Internal/Data/Stream/IsStream/Transform.hs+2−2 src/Streamly/Internal/FileSystem/Handle.hs+19−91 streamly.cabal+4
benchmark/Streamly/Benchmark/FileSystem/Handle/ReadWrite.hs+3−3
@@ -103,7 +103,7 @@ o_1_space_copy_read env =
103103
104104-- | Send the file contents to /dev/null
105105readFromBytesNull :: Handle -> Handle -> IO ()
106−readFromBytesNull inh devNull = IFH.fromBytes devNull $ S.unfold FH.read inh
106+readFromBytesNull inh devNull = IFH.putBytes devNull $ S.unfold FH.read inh
107107
108108#ifdef INSPECTION
109109inspect $ hasNoTypeClasses 'readFromBytesNull
@@ -116,7 +116,7 @@ inspect $ 'readFromBytesNull `hasNoType` ''D.FoldMany
116116-- | Send the file contents ('defaultChunkSize') to /dev/null
117117readWithBufferOfFromBytesNull :: Handle -> Handle -> IO ()
118118readWithBufferOfFromBytesNull inh devNull =
119− IFH.fromBytes devNull
119+ IFH.putBytes devNull
120120 $ S.unfold FH.readWithBufferOf (defaultChunkSize, inh)
121121
122122#ifdef INSPECTION
@@ -150,7 +150,7 @@ _readChunksWithBufferOf inh devNull = IUF.fold fld unf (defaultChunkSize, inh)
150150
151151o_1_space_copy_fromBytes :: BenchEnv -> [Benchmark]
152152o_1_space_copy_fromBytes env =
153− [ bgroup "copy/fromBytes"
153+ [ bgroup "copy/putBytes"
154154 [ mkBench "rawToNull" env $ \inh _ ->
155155 readFromBytesNull inh (nullH env)
156156 , mkBench "FH.readWithBufferOf" env $ \inh _ ->
benchmark/Streamly/Benchmark/Prelude/Serial/Exceptions.hs+2−2
@@ -71,7 +71,7 @@ fromToBytesBracket_Stream :: Handle -> Handle -> IO ()
7171fromToBytesBracket_Stream inh devNull =
7272 let readEx = IP.bracket_ (return ()) (\_ -> hClose inh)
7373 (\_ -> IFH.toBytes inh)
74− in IFH.fromBytes devNull $ readEx
74+ in IFH.putBytes devNull $ readEx
7575
7676#ifdef INSPECTION
7777inspect $ hasNoTypeClasses 'fromToBytesBracket_Stream
@@ -82,7 +82,7 @@ fromToBytesBracketStream :: Handle -> Handle -> IO ()
8282fromToBytesBracketStream inh devNull =
8383 let readEx = S.bracket (return ()) (\_ -> hClose inh)
8484 (\_ -> IFH.toBytes inh)
85− in IFH.fromBytes devNull $ readEx
85+ in IFH.putBytes devNull $ readEx
8686
8787readWriteBeforeAfterStream :: Handle -> Handle -> IO ()
8888readWriteBeforeAfterStream inh devNull =
design/container-api.mdnew file+65
@@ -0,0 +1,65 @@
1+# Data Containers
2+
3+Containers are persistent containers of data e.g. files, arrays, maps. For
4+consistency we use similar API for all such containers where possible. Usually
5+the API names are relative to the current module e.g. toBytes in an array
6+module means converting the array to bytes, it sounds intuitive if read
7+qualified with the module name e.g. Array.toBytes. This doc lists some
8+conventions and guidelines to be followed.
9+
10+## Unfolds and Folds
11+
12+* Unfolds are named as "read" or with a "read" prefix (e.g. readChunks).
13+* Folds are named as "write" or with a "write" prefix (e.g. writeChunks).
14+
15+## From and Put
16+
17+* Immutable construction from some external source is named with a "from"
18+ prefix (e.g. fromList).
19+* Mutation of an existing container uses a "put" prefix instead of "from". When
20+ an API uses an existing container to write to and does not return a newly
21+ constructed container then use "put".
22+* "from" vs "put": "from" assumes creation of a new object, it may fail if the
23+ object being created already exists (e.g. the file exists), it may not take a
24+ lock as it assumes immutability. "put" may create a new object or overwrite
25+ an existing one, it may take a lock for writing as it assumes mutability.
26+
27+## To and Get
28+
29+* Converting the complete object to an external representation is prefixed with
30+ "to" (e.g. toBytes).
31+* For mutable objects "get" APIs may be used instead of "to" APIs.
32+* "to" vs "get": "to" assumes immutable object so does not have to take a lock.
33+ "get" assumes mutable object so may take a lock.
34+
35+## Append
36+
37+* Use "append" prefix for appending data at the end of a mutable container
38+
39+## Random Access (Arrays)
40+
41+* getIndex (for arrays)
42+* getSlice/getRange/getIndices
43+* putIndex (for mutable arrays)
44+* append (for mutable arrays)
45+
46+## Key Access (Maps)
47+
48+* getKey
49+* findKey (test existence)
50+* createKey (insert new key for mutable maps)
51+* putKey (insert or update for mutable maps)
52+* updateKey (update existing or fail)
53+* deleteKey (delete existing or fail)
54+* destroyKey (delete existing or not)
55+
56+## Points to Consider
57+
58+The fold and unfold APIs can be used to express the to/from stream APIs. So we
59+may not need both, it may just add to more APIs being proliferated.
60+
61+We may need an "append" style fold as well? What would "stream" append
62+operations be called then?
63+
64+We may need locked version of "write" folds for mutable containers for
65+concurrent access.
src/Streamly/Console/Stdio.hsnew file+31
@@ -0,0 +1,31 @@
1+-- |
2+-- Module : Streamly.Console.Stdio
3+-- Copyright : (c) 2021 Composewell Technologies
4+--
5+-- License : BSD-3-Clause
6+-- Maintainer : streamly@composewell.com
7+-- Stability : experimental
8+-- Portability : GHC
9+--
10+-- Combinators to work with standard input, output and error streams.
11+--
12+-- See also: "Streamly.Internal.Console.Stdio"
13+
14+module Streamly.Console.Stdio
15+ (
16+ -- * Read (stdin)
17+ read
18+ , readChunks
19+
20+ -- * Write (stdout)
21+ , write
22+ , writeChunks
23+
24+ -- * Write (stderr)
25+ , writeErr
26+ , writeErrChunks
27+ )
28+where
29+
30+import Streamly.Internal.Console.Stdio
31+import Prelude hiding (read)
src/Streamly/Internal/Console/Stdio.hsnew file+229
@@ -0,0 +1,229 @@
1+-- |
2+-- Module : Streamly.Internal.Console.Stdio
3+-- Copyright : (c) 2018 Composewell Technologies
4+--
5+-- License : BSD-3-Clause
6+-- Maintainer : streamly@composewell.com
7+-- Stability : experimental
8+-- Portability : GHC
9+
10+module Streamly.Internal.Console.Stdio
11+ (
12+ -- * Read
13+ read
14+ , getBytes
15+ , getChars
16+ , readChunks
17+ , getChunks
18+ -- , getChunksLn
19+ -- , getStringsWith -- get strings using the supplied decoding
20+ -- , getStrings -- get strings of complete chars,
21+ -- leave any partial chars for next string
22+ -- , getStringsLn -- get lines decoded as char strings
23+
24+ -- * Write
25+ , write
26+ , writeErr
27+ , putBytes -- Buffered (32K)
28+ , putChars
29+ , writeChunks
30+ , writeErrChunks
31+ , putChunks -- Unbuffered
32+ , putStringsWith
33+ , putStrings
34+ , putStringsLn
35+ )
36+where
37+
38+#include "inline.hs"
39+
40+import Control.Monad.IO.Class (MonadIO(..))
41+import Data.Word (Word8)
42+import System.IO (stdin, stdout, stderr)
43+import Prelude hiding (read)
44+
45+import Streamly.Internal.Data.Array.Foreign.Type (Array(..))
46+import Streamly.Internal.Data.Stream.Serial (SerialT)
47+import Streamly.Internal.Data.Unfold (Unfold)
48+import Streamly.Internal.Data.Fold (Fold)
49+
50+import qualified Streamly.Internal.Data.Array.Foreign as Array
51+import qualified Streamly.Internal.Data.Stream.IsStream as Stream
52+import qualified Streamly.Internal.Data.Unfold as Unfold
53+import qualified Streamly.Internal.FileSystem.Handle as Handle
54+import qualified Streamly.Internal.Unicode.Stream as Unicode
55+
56+-------------------------------------------------------------------------------
57+-- Reads
58+-------------------------------------------------------------------------------
59+
60+-- | Unfold standard input into a stream of 'Word8'.
61+--
62+-- /Pre-release/
63+{-# INLINE read #-}
64+read :: MonadIO m => Unfold m () Word8
65+read = Unfold.lmap (\() -> stdin) Handle.read
66+
67+-- | Read a byte stream from standard input.
68+--
69+-- > getBytes = Handle.toBytes stdin
70+-- > getBytes = Stream.unfold Stdio.read ()
71+--
72+-- /Pre-release/
73+--
74+{-# INLINE getBytes #-}
75+getBytes :: MonadIO m => SerialT m Word8
76+getBytes = Handle.toBytes stdin
77+
78+-- | Read a character stream from Utf8 encoded standard input.
79+--
80+-- > getChars = Unicode.decodeUtf8 Stdio.getBytes
81+--
82+-- /Pre-release/
83+--
84+{-# INLINE getChars #-}
85+getChars :: MonadIO m => SerialT m Char
86+getChars = Unicode.decodeUtf8 getBytes
87+
88+-- | Unfolds standard input into a stream of 'Word8' arrays.
89+--
90+-- /Pre-release/
91+{-# INLINE readChunks #-}
92+readChunks :: MonadIO m => Unfold m () (Array Word8)
93+readChunks = Unfold.lmap (\() -> stdin) Handle.readChunks
94+
95+-- | Read a stream of chunks from standard input. The maximum size of a single
96+-- chunk is limited to @defaultChunkSize@. The actual size read may be less
97+-- than @defaultChunkSize@.
98+--
99+-- > getChunks = Handle.toChunks stdin
100+-- > getChunks = Stream.unfold Stdio.readChunks ()
101+--
102+-- /Pre-release/
103+--
104+{-# INLINE getChunks #-}
105+getChunks :: MonadIO m => SerialT m (Array Word8)
106+getChunks = Handle.toChunks stdin
107+
108+{-
109+-- | Read UTF8 encoded lines from standard input.
110+--
111+-- You may want to process the input byte stream directly using appropriate
112+-- folds for more efficient processing.
113+--
114+-- /Pre-release/
115+--
116+{-# INLINE getChunksLn #-}
117+getChunksLn :: MonadIO m => SerialT m (Array Word8)
118+getChunksLn = (Stream.splitWithSuffix (== '\n') f) getChars
119+
120+ -- XXX Need to implement Fold.unfoldMany, should be easy for
121+ -- non-terminating folds, but may be tricky for terminating folds. See
122+ -- Array Stream folds.
123+ where f = Fold.unfoldMany Unicode.readCharUtf8 Array.write
124+-}
125+
126+-------------------------------------------------------------------------------
127+-- Writes
128+-------------------------------------------------------------------------------
129+
130+-- | Fold a stream of 'Word8' to standard output.
131+--
132+-- /Pre-release/
133+{-# INLINE write #-}
134+write :: MonadIO m => Fold m Word8 ()
135+write = Handle.write stdout
136+
137+-- | Fold a stream of 'Word8' to standard error.
138+--
139+-- /Pre-release/
140+{-# INLINE writeErr #-}
141+writeErr :: MonadIO m => Fold m Word8 ()
142+writeErr = Handle.write stderr
143+
144+-- | Write a stream of bytes to standard output.
145+--
146+-- > putBytes = Handle.putBytes stdout
147+-- > putBytes = Stream.fold Stdio.write
148+--
149+-- /Pre-release/
150+--
151+{-# INLINE putBytes #-}
152+putBytes :: MonadIO m => SerialT m Word8 -> m ()
153+putBytes = Handle.putBytes stdout
154+
155+-- | Encode a character stream to Utf8 and write it to standard output.
156+--
157+-- > putChars = Stdio.putBytes . Unicode.encodeUtf8
158+--
159+-- /Pre-release/
160+--
161+{-# INLINE putChars #-}
162+putChars :: MonadIO m => SerialT m Char -> m ()
163+putChars = putBytes . Unicode.encodeUtf8
164+
165+-- | Fold a stream of @Array Word8@ to standard output.
166+--
167+-- /Pre-release/
168+{-# INLINE writeChunks #-}
169+writeChunks :: MonadIO m => Fold m (Array Word8) ()
170+writeChunks = Handle.writeChunks stdout
171+
172+-- | Fold a stream of @Array Word8@ to standard error.
173+--
174+-- /Pre-release/
175+{-# INLINE writeErrChunks #-}
176+writeErrChunks :: MonadIO m => Fold m (Array Word8) ()
177+writeErrChunks = Handle.writeChunks stderr
178+
179+-- | Write a stream of chunks to standard output.
180+--
181+-- > putChunks = Handle.putChunks stdout
182+-- > putChunks = Stream.fold Stdio.writeChunks
183+--
184+-- /Pre-release/
185+--
186+{-# INLINE putChunks #-}
187+putChunks :: MonadIO m => SerialT m (Array Word8) -> m ()
188+putChunks = Handle.putChunks stdout
189+
190+-------------------------------------------------------------------------------
191+-- Line buffered
192+-------------------------------------------------------------------------------
193+
194+-- XXX We need to write transformations as pipes so that they can be applied to
195+-- folds as well as unfolds/streams. Non-backtracking (one-to-one, one-to-many,
196+-- filters, reducers) transformations may be easy so we can possibly start with
197+-- those.
198+--
199+-- | Write a stream of strings to standard output using the supplied encoding.
200+-- Output is flushed to the device for each string.
201+--
202+-- /Pre-release/
203+--
204+{-# INLINE putStringsWith #-}
205+putStringsWith :: MonadIO m
206+ => (SerialT m Char -> SerialT m Word8) -> SerialT m String -> m ()
207+putStringsWith encode = putChunks . Unicode.encodeStrings encode
208+
209+-- | Write a stream of strings to standard output using UTF8 encoding. Output
210+-- is flushed to the device for each string.
211+--
212+-- /Pre-release/
213+--
214+{-# INLINE putStrings #-}
215+putStrings :: MonadIO m => SerialT m String -> m ()
216+putStrings = putStringsWith Unicode.encodeUtf8
217+
218+-- | Like 'putStrings' but adds a newline at the end of each string.
219+--
220+-- XXX This is not portable, on Windows we need to use "\r\n" instead.
221+--
222+-- /Pre-release/
223+--
224+{-# INLINE putStringsLn #-}
225+putStringsLn :: MonadIO m => SerialT m String -> m ()
226+putStringsLn =
227+ putChunks
228+ . Stream.intersperseSuffix (return $ Array.fromList [10])
229+ . Unicode.encodeStrings Unicode.encodeUtf8
src/Streamly/Internal/Data/Stream/IsStream/Transform.hs+2−2
@@ -1148,7 +1148,7 @@ intersperseBySpan _n _f _xs = undefined
11481148--
11491149-- /Pre-release/
11501150{-# INLINE intersperseSuffix #-}
1151−intersperseSuffix :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
1151+intersperseSuffix :: (IsStream t, Monad m) => m a -> t m a -> t m a
11521152intersperseSuffix m = fromStreamD . D.intersperseSuffix m . toStreamD
11531153
11541154-- | Insert a side effect after consuming an element of a stream.
@@ -1174,7 +1174,7 @@ intersperseSuffix_ m = fromStreamD . D.intersperseSuffix_ m . toStreamD
11741174-- /Pre-release/
11751175--
11761176{-# INLINE intersperseSuffixBySpan #-}
1177−intersperseSuffixBySpan :: (IsStream t, MonadAsync m)
1177+intersperseSuffixBySpan :: (IsStream t, Monad m)
11781178 => Int -> m a -> t m a -> t m a
11791179intersperseSuffixBySpan n eff =
11801180 fromStreamD . D.intersperseSuffixBySpan n eff . toStreamD
src/Streamly/Internal/FileSystem/Handle.hs+19−91
@@ -20,7 +20,6 @@ module Streamly.Internal.FileSystem.Handle
2020
2121 , toBytes
2222 , toBytesWithBufferOf
23− , getBytes
2423
2524 -- -- * Array Read
2625 -- , readArrayUpto
@@ -30,7 +29,6 @@ module Streamly.Internal.FileSystem.Handle
3029
3130 , toChunksWithBufferOf
3231 , toChunks
33− , getChunks
3432
3533 -- ** Write to Handle
3634 -- Byte stream write (Folds)
@@ -43,8 +41,8 @@ module Streamly.Internal.FileSystem.Handle
4341 , writeWithBufferOf
4442
4543 -- Byte stream write (Streams)
46− , fromBytes
47− , fromBytesWithBufferOf
44+ , putBytes
45+ , putBytesWithBufferOf
4846
4947 -- -- * Array Write
5048 , writeArray
@@ -52,12 +50,8 @@ module Streamly.Internal.FileSystem.Handle
5250 , writeChunksWithBufferOf
5351
5452 -- -- * Array stream Write
55− , fromChunksWithBufferOf
56− , fromChunks
53+ , putChunksWithBufferOf
5754 , putChunks
58− , putStrings
59− , putBytes
60− , putLines
6155
6256 -- -- * Random Access (Seek)
6357 -- -- | Unlike the streaming APIs listed above, these APIs apply to devices or
@@ -106,10 +100,9 @@ import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
106100import Foreign.Ptr (minusPtr, plusPtr)
107101import Foreign.Storable (Storable(..))
108102import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
109−import System.IO (Handle, hGetBufSome, hPutBuf, stdin, stdout)
103+import System.IO (Handle, hGetBufSome, hPutBuf)
110104import Prelude hiding (read)
111105
112−import Streamly.Prelude (MonadAsync)
113106import Streamly.Data.Fold (Fold)
114107import Streamly.Internal.Data.Fold.Type (Fold2(..))
115108import Streamly.Internal.Data.Unfold.Type (Unfold(..))
@@ -124,7 +117,6 @@ import Streamly.Internal.Data.Array.Stream.Foreign (lpackArraysChunksOf)
124117import qualified Streamly.Data.Fold as FL
125118import qualified Streamly.Internal.Data.Fold.Type as FL
126119import qualified Streamly.Internal.Data.Unfold as UF
127−import qualified Streamly.Internal.Data.Array.Foreign as IA
128120import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
129121import qualified Streamly.Internal.Data.Stream.IsStream as S
130122import qualified Streamly.Data.Array.Foreign as A
@@ -231,28 +223,6 @@ readChunksWithBufferOf = Unfold step return
231223toChunks :: (IsStream t, MonadIO m) => Handle -> t m (Array Word8)
232224toChunks = toChunksWithBufferOf defaultChunkSize
233225
234−-- | Read a stream of chunks from standard input. The maximum size of a single
235−-- chunk is limited to @defaultChunkSize@. The actual size read may be less
236−-- than @defaultChunkSize@.
237−--
238−-- > getChunks = toChunks stdin
239−--
240−-- /Pre-release/
241−--
242−{-# INLINE getChunks #-}
243−getChunks :: (IsStream t, MonadIO m) => t m (Array Word8)
244−getChunks = toChunks stdin
245−
246−-- | Read a stream of bytes from standard input.
247−--
248−-- > getBytes = toBytes stdin
249−--
250−-- /Pre-release/
251−--
252−{-# INLINE getBytes #-}
253−getBytes :: (IsStream t, MonadIO m) => t m Word8
254−getBytes = toBytes stdin
255−
256226-- | Unfolds a handle into a stream of 'Word8' arrays. Requests to the IO
257227-- device are performed using a buffer of size
258228-- 'Streamly.Internal.Data.Array.Foreign.Type.defaultChunkSize'. The
@@ -340,73 +310,31 @@ writeArray h Array{..} = withForeignPtr aStart $ \p -> hPutBuf h p aLen
340310-- | Write a stream of arrays to a handle.
341311--
342312-- @since 0.7.0
343−{-# INLINE fromChunks #-}
344−fromChunks :: (MonadIO m, Storable a)
345− => Handle -> SerialT m (Array a) -> m ()
346−fromChunks h = S.mapM_ (liftIO . writeArray h)
347−
348−-- | Write a stream of chunks to standard output.
349−--
350−-- /Pre-release/
351−--
352313{-# INLINE putChunks #-}
353−putChunks :: (MonadIO m, Storable a) => SerialT m (Array a) -> m ()
354−putChunks = fromChunks stdout
355−
356−-- XXX use an unfold so that we can put any type of strings.
357−-- | Write a stream of strings to standard output using the supplied encoding.
358−-- Output is flushed to the device for each string.
359−--
360−-- /Pre-release/
361−--
362−{-# INLINE putStrings #-}
363−putStrings :: MonadAsync m
364− => (SerialT m Char -> SerialT m Word8) -> SerialT m String -> m ()
365−putStrings encode = putChunks . S.mapM (IA.fromStream . encode . S.fromList)
366−
367−-- XXX use an unfold so that we can put lines from any object
368−-- | Write a stream of strings as separate lines to standard output using the
369−-- supplied encoding. Output is line buffered i.e. the output is written to the
370−-- device as soon as a newline is encountered.
371−--
372−-- /Pre-release/
373−--
374−{-# INLINE putLines #-}
375−putLines :: MonadAsync m
376− => (SerialT m Char -> SerialT m Word8) -> SerialT m String -> m ()
377−putLines encode = putChunks . S.mapM
378− (\xs -> IA.fromStream $ encode (S.fromList (xs ++ "\n")))
379−
380−-- | Write a stream of bytes from standard output.
381−--
382−-- > putBytes = fromBytes stdout
383−--
384−-- /Pre-release/
385−--
386−{-# INLINE putBytes #-}
387−putBytes :: MonadIO m => SerialT m Word8 -> m ()
388−putBytes = fromBytes stdout
314+putChunks :: (MonadIO m, Storable a)
315+ => Handle -> SerialT m (Array a) -> m ()
316+putChunks h = S.mapM_ (liftIO . writeArray h)
389317
390−-- | @fromChunksWithBufferOf bufsize handle stream@ writes a stream of arrays
318+-- | @putChunksWithBufferOf bufsize handle stream@ writes a stream of arrays
391319-- to @handle@ after coalescing the adjacent arrays in chunks of @bufsize@.
392320-- The chunk size is only a maximum and the actual writes could be smaller as
393321-- we do not split the arrays to fit exactly to the specified size.
394322--
395323-- @since 0.7.0
396−{-# INLINE fromChunksWithBufferOf #-}
397−fromChunksWithBufferOf :: (MonadIO m, Storable a)
324+{-# INLINE putChunksWithBufferOf #-}
325+putChunksWithBufferOf :: (MonadIO m, Storable a)
398326 => Int -> Handle -> SerialT m (Array a) -> m ()
399−fromChunksWithBufferOf n h xs = fromChunks h $ AS.compact n xs
327+putChunksWithBufferOf n h xs = putChunks h $ AS.compact n xs
400328
401−-- | @fromBytesWithBufferOf bufsize handle stream@ writes @stream@ to @handle@
329+-- | @putBytesWithBufferOf bufsize handle stream@ writes @stream@ to @handle@
402330-- in chunks of @bufsize@. A write is performed to the IO device as soon as we
403331-- collect the required input size.
404332--
405333-- @since 0.7.0
406−{-# INLINE fromBytesWithBufferOf #-}
407−fromBytesWithBufferOf :: MonadIO m => Int -> Handle -> SerialT m Word8 -> m ()
408−fromBytesWithBufferOf n h m = fromChunks h $ S.arraysOf n m
409−-- fromBytesWithBufferOf n h m = fromChunks h $ AS.arraysOf n m
334+{-# INLINE putBytesWithBufferOf #-}
335+putBytesWithBufferOf :: MonadIO m => Int -> Handle -> SerialT m Word8 -> m ()
336+putBytesWithBufferOf n h m = putChunks h $ S.arraysOf n m
337+-- putBytesWithBufferOf n h m = putChunks h $ AS.arraysOf n m
410338
411339-- > write = 'writeWithBufferOf' A.defaultChunkSize
412340--
@@ -417,9 +345,9 @@ fromBytesWithBufferOf n h m = fromChunks h $ S.arraysOf n m
417345-- need some extra perf boost.
418346--
419347-- @since 0.7.0
420−{-# INLINE fromBytes #-}
421−fromBytes :: MonadIO m => Handle -> SerialT m Word8 -> m ()
422−fromBytes = fromBytesWithBufferOf defaultChunkSize
348+{-# INLINE putBytes #-}
349+putBytes :: MonadIO m => Handle -> SerialT m Word8 -> m ()
350+putBytes = putBytesWithBufferOf defaultChunkSize
423351
424352-- | Write a stream of arrays to a handle. Each array in the stream is written
425353-- to the device as a separate IO request.
streamly.cabal+4
@@ -364,6 +364,7 @@ library
364364
365365 -- Filesystem/IO
366366 , Streamly.FileSystem.Handle
367+ , Streamly.Console.Stdio
367368
368369 -- Network/IO
369370 , Streamly.Network.Socket
@@ -504,6 +505,9 @@ library
504505 , Streamly.Internal.FileSystem.FDIO
505506 , Streamly.Internal.FileSystem.FD
506507
508+ -- streamly-console
509+ , Streamly.Internal.Console.Stdio
510+
507511 -- streamly-network
508512 , Streamly.Internal.Network.Socket
509513 , Streamly.Internal.Network.Inet.TCP