on master help sign in
Split stdio ops into a Console.Stdio module
6132eb3Harendra Kumar
benchmark/Streamly/Benchmark/FileSystem/Handle/ReadWrite.hs+3−3
@@ -103,7 +103,7 @@ o_1_space_copy_read env =
103
103
104-- | Send the file contents to /dev/null
104-- | Send the file contents to /dev/null
105readFromBytesNull :: Handle -> Handle -> IO ()
105readFromBytesNull :: 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
107
107
108#ifdef INSPECTION
108#ifdef INSPECTION
109inspect $ hasNoTypeClasses 'readFromBytesNull
109inspect $ hasNoTypeClasses 'readFromBytesNull
@@ -116,7 +116,7 @@ inspect $ 'readFromBytesNull `hasNoType` ''D.FoldMany
116-- | Send the file contents ('defaultChunkSize') to /dev/null
116-- | Send the file contents ('defaultChunkSize') to /dev/null
117readWithBufferOfFromBytesNull :: Handle -> Handle -> IO ()
117readWithBufferOfFromBytesNull :: Handle -> Handle -> IO ()
118readWithBufferOfFromBytesNull inh devNull =
118readWithBufferOfFromBytesNull inh devNull =
119− IFH.fromBytes devNull
119+ IFH.putBytes devNull
120 $ S.unfold FH.readWithBufferOf (defaultChunkSize, inh)
120 $ S.unfold FH.readWithBufferOf (defaultChunkSize, inh)
121
121
122#ifdef INSPECTION
122#ifdef INSPECTION
@@ -150,7 +150,7 @@ _readChunksWithBufferOf inh devNull = IUF.fold fld unf (defaultChunkSize, inh)
150
150
151o_1_space_copy_fromBytes :: BenchEnv -> [Benchmark]
151o_1_space_copy_fromBytes :: BenchEnv -> [Benchmark]
152o_1_space_copy_fromBytes env =
152o_1_space_copy_fromBytes env =
153− [ bgroup "copy/fromBytes"
153+ [ bgroup "copy/putBytes"
154 [ mkBench "rawToNull" env $ \inh _ ->
154 [ mkBench "rawToNull" env $ \inh _ ->
155 readFromBytesNull inh (nullH env)
155 readFromBytesNull inh (nullH env)
156 , mkBench "FH.readWithBufferOf" env $ \inh _ ->
156 , mkBench "FH.readWithBufferOf" env $ \inh _ ->
benchmark/Streamly/Benchmark/Prelude/Serial/Exceptions.hs+2−2
@@ -71,7 +71,7 @@ fromToBytesBracket_Stream :: Handle -> Handle -> IO ()
71fromToBytesBracket_Stream inh devNull =
71fromToBytesBracket_Stream inh devNull =
72 let readEx = IP.bracket_ (return ()) (\_ -> hClose inh)
72 let readEx = IP.bracket_ (return ()) (\_ -> hClose inh)
73 (\_ -> IFH.toBytes inh)
73 (\_ -> IFH.toBytes inh)
74− in IFH.fromBytes devNull $ readEx
74+ in IFH.putBytes devNull $ readEx
75
75
76#ifdef INSPECTION
76#ifdef INSPECTION
77inspect $ hasNoTypeClasses 'fromToBytesBracket_Stream
77inspect $ hasNoTypeClasses 'fromToBytesBracket_Stream
@@ -82,7 +82,7 @@ fromToBytesBracketStream :: Handle -> Handle -> IO ()
82fromToBytesBracketStream inh devNull =
82fromToBytesBracketStream inh devNull =
83 let readEx = S.bracket (return ()) (\_ -> hClose inh)
83 let readEx = S.bracket (return ()) (\_ -> hClose inh)
84 (\_ -> IFH.toBytes inh)
84 (\_ -> IFH.toBytes inh)
85− in IFH.fromBytes devNull $ readEx
85+ in IFH.putBytes devNull $ readEx
86
86
87readWriteBeforeAfterStream :: Handle -> Handle -> IO ()
87readWriteBeforeAfterStream :: Handle -> Handle -> IO ()
88readWriteBeforeAfterStream inh devNull =
88readWriteBeforeAfterStream 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
1148--
1148--
1149-- /Pre-release/
1149-- /Pre-release/
1150{-# INLINE intersperseSuffix #-}
1150{-# 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
1152intersperseSuffix m = fromStreamD . D.intersperseSuffix m . toStreamD
1152intersperseSuffix m = fromStreamD . D.intersperseSuffix m . toStreamD
1153
1153
1154-- | Insert a side effect after consuming an element of a stream.
1154-- | Insert a side effect after consuming an element of a stream.
@@ -1174,7 +1174,7 @@ intersperseSuffix_ m = fromStreamD . D.intersperseSuffix_ m . toStreamD
1174-- /Pre-release/
1174-- /Pre-release/
1175--
1175--
1176{-# INLINE intersperseSuffixBySpan #-}
1176{-# INLINE intersperseSuffixBySpan #-}
1177−intersperseSuffixBySpan :: (IsStream t, MonadAsync m)
1177+intersperseSuffixBySpan :: (IsStream t, Monad m)
1178 => Int -> m a -> t m a -> t m a
1178 => Int -> m a -> t m a -> t m a
1179intersperseSuffixBySpan n eff =
1179intersperseSuffixBySpan n eff =
1180 fromStreamD . D.intersperseSuffixBySpan n eff . toStreamD
1180 fromStreamD . D.intersperseSuffixBySpan n eff . toStreamD
src/Streamly/Internal/FileSystem/Handle.hs+19−91
@@ -20,7 +20,6 @@ module Streamly.Internal.FileSystem.Handle
20
20
21 , toBytes
21 , toBytes
22 , toBytesWithBufferOf
22 , toBytesWithBufferOf
23− , getBytes
24
23
25 -- -- * Array Read
24 -- -- * Array Read
26 -- , readArrayUpto
25 -- , readArrayUpto
@@ -30,7 +29,6 @@ module Streamly.Internal.FileSystem.Handle
30
29
31 , toChunksWithBufferOf
30 , toChunksWithBufferOf
32 , toChunks
31 , toChunks
33− , getChunks
34
32
35 -- ** Write to Handle
33 -- ** Write to Handle
36 -- Byte stream write (Folds)
34 -- Byte stream write (Folds)
@@ -43,8 +41,8 @@ module Streamly.Internal.FileSystem.Handle
43 , writeWithBufferOf
41 , writeWithBufferOf
44
42
45 -- Byte stream write (Streams)
43 -- Byte stream write (Streams)
46− , fromBytes
44+ , putBytes
47− , fromBytesWithBufferOf
45+ , putBytesWithBufferOf
48
46
49 -- -- * Array Write
47 -- -- * Array Write
50 , writeArray
48 , writeArray
@@ -52,12 +50,8 @@ module Streamly.Internal.FileSystem.Handle
52 , writeChunksWithBufferOf
50 , writeChunksWithBufferOf
53
51
54 -- -- * Array stream Write
52 -- -- * Array stream Write
55− , fromChunksWithBufferOf
53+ , putChunksWithBufferOf
56− , fromChunks
57 , putChunks
54 , putChunks
58− , putStrings
59− , putBytes
60− , putLines
61
55
62 -- -- * Random Access (Seek)
56 -- -- * Random Access (Seek)
63 -- -- | Unlike the streaming APIs listed above, these APIs apply to devices or
57 -- -- | Unlike the streaming APIs listed above, these APIs apply to devices or
@@ -106,10 +100,9 @@ import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
106import Foreign.Ptr (minusPtr, plusPtr)
100import Foreign.Ptr (minusPtr, plusPtr)
107import Foreign.Storable (Storable(..))
101import Foreign.Storable (Storable(..))
108import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
102import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
109−import System.IO (Handle, hGetBufSome, hPutBuf, stdin, stdout)
103+import System.IO (Handle, hGetBufSome, hPutBuf)
110import Prelude hiding (read)
104import Prelude hiding (read)
111
105
112−import Streamly.Prelude (MonadAsync)
113import Streamly.Data.Fold (Fold)
106import Streamly.Data.Fold (Fold)
114import Streamly.Internal.Data.Fold.Type (Fold2(..))
107import Streamly.Internal.Data.Fold.Type (Fold2(..))
115import Streamly.Internal.Data.Unfold.Type (Unfold(..))
108import Streamly.Internal.Data.Unfold.Type (Unfold(..))
@@ -124,7 +117,6 @@ import Streamly.Internal.Data.Array.Stream.Foreign (lpackArraysChunksOf)
124import qualified Streamly.Data.Fold as FL
117import qualified Streamly.Data.Fold as FL
125import qualified Streamly.Internal.Data.Fold.Type as FL
118import qualified Streamly.Internal.Data.Fold.Type as FL
126import qualified Streamly.Internal.Data.Unfold as UF
119import qualified Streamly.Internal.Data.Unfold as UF
127−import qualified Streamly.Internal.Data.Array.Foreign as IA
128import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
120import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
129import qualified Streamly.Internal.Data.Stream.IsStream as S
121import qualified Streamly.Internal.Data.Stream.IsStream as S
130import qualified Streamly.Data.Array.Foreign as A
122import qualified Streamly.Data.Array.Foreign as A
@@ -231,28 +223,6 @@ readChunksWithBufferOf = Unfold step return
231toChunks :: (IsStream t, MonadIO m) => Handle -> t m (Array Word8)
223toChunks :: (IsStream t, MonadIO m) => Handle -> t m (Array Word8)
232toChunks = toChunksWithBufferOf defaultChunkSize
224toChunks = toChunksWithBufferOf defaultChunkSize
233
225
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−
256-- | Unfolds a handle into a stream of 'Word8' arrays. Requests to the IO
226-- | Unfolds a handle into a stream of 'Word8' arrays. Requests to the IO
257-- device are performed using a buffer of size
227-- device are performed using a buffer of size
258-- 'Streamly.Internal.Data.Array.Foreign.Type.defaultChunkSize'. The
228-- 'Streamly.Internal.Data.Array.Foreign.Type.defaultChunkSize'. The
@@ -340,73 +310,31 @@ writeArray h Array{..} = withForeignPtr aStart $ \p -> hPutBuf h p aLen
340-- | Write a stream of arrays to a handle.
310-- | Write a stream of arrays to a handle.
341--
311--
342-- @since 0.7.0
312-- @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−--
352{-# INLINE putChunks #-}
313{-# INLINE putChunks #-}
353−putChunks :: (MonadIO m, Storable a) => SerialT m (Array a) -> m ()
314+putChunks :: (MonadIO m, Storable a)
354−putChunks = fromChunks stdout
315+ => Handle -> SerialT m (Array a) -> m ()
355−
316+putChunks h = S.mapM_ (liftIO . writeArray h)
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
389
317
390−-- | @fromChunksWithBufferOf bufsize handle stream@ writes a stream of arrays
318+-- | @putChunksWithBufferOf bufsize handle stream@ writes a stream of arrays
391-- to @handle@ after coalescing the adjacent arrays in chunks of @bufsize@.
319-- to @handle@ after coalescing the adjacent arrays in chunks of @bufsize@.
392-- The chunk size is only a maximum and the actual writes could be smaller as
320-- The chunk size is only a maximum and the actual writes could be smaller as
393-- we do not split the arrays to fit exactly to the specified size.
321-- we do not split the arrays to fit exactly to the specified size.
394--
322--
395-- @since 0.7.0
323-- @since 0.7.0
396−{-# INLINE fromChunksWithBufferOf #-}
324+{-# INLINE putChunksWithBufferOf #-}
397−fromChunksWithBufferOf :: (MonadIO m, Storable a)
325+putChunksWithBufferOf :: (MonadIO m, Storable a)
398 => Int -> Handle -> SerialT m (Array a) -> m ()
326 => 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
400
328
401−-- | @fromBytesWithBufferOf bufsize handle stream@ writes @stream@ to @handle@
329+-- | @putBytesWithBufferOf bufsize handle stream@ writes @stream@ to @handle@
402-- in chunks of @bufsize@. A write is performed to the IO device as soon as we
330-- in chunks of @bufsize@. A write is performed to the IO device as soon as we
403-- collect the required input size.
331-- collect the required input size.
404--
332--
405-- @since 0.7.0
333-- @since 0.7.0
406−{-# INLINE fromBytesWithBufferOf #-}
334+{-# INLINE putBytesWithBufferOf #-}
407−fromBytesWithBufferOf :: MonadIO m => Int -> Handle -> SerialT m Word8 -> m ()
335+putBytesWithBufferOf :: MonadIO m => Int -> Handle -> SerialT m Word8 -> m ()
408−fromBytesWithBufferOf n h m = fromChunks h $ S.arraysOf n m
336+putBytesWithBufferOf n h m = putChunks h $ S.arraysOf n m
409−-- fromBytesWithBufferOf n h m = fromChunks h $ AS.arraysOf n m
337+-- putBytesWithBufferOf n h m = putChunks h $ AS.arraysOf n m
410
338
411-- > write = 'writeWithBufferOf' A.defaultChunkSize
339-- > write = 'writeWithBufferOf' A.defaultChunkSize
412--
340--
@@ -417,9 +345,9 @@ fromBytesWithBufferOf n h m = fromChunks h $ S.arraysOf n m
417-- need some extra perf boost.
345-- need some extra perf boost.
418--
346--
419-- @since 0.7.0
347-- @since 0.7.0
420−{-# INLINE fromBytes #-}
348+{-# INLINE putBytes #-}
421−fromBytes :: MonadIO m => Handle -> SerialT m Word8 -> m ()
349+putBytes :: MonadIO m => Handle -> SerialT m Word8 -> m ()
422−fromBytes = fromBytesWithBufferOf defaultChunkSize
350+putBytes = putBytesWithBufferOf defaultChunkSize
423
351
424-- | Write a stream of arrays to a handle. Each array in the stream is written
352-- | Write a stream of arrays to a handle. Each array in the stream is written
425-- to the device as a separate IO request.
353-- to the device as a separate IO request.
streamly.cabal+4
@@ -364,6 +364,7 @@ library
364
364
365 -- Filesystem/IO
365 -- Filesystem/IO
366 , Streamly.FileSystem.Handle
366 , Streamly.FileSystem.Handle
367+ , Streamly.Console.Stdio
367
368
368 -- Network/IO
369 -- Network/IO
369 , Streamly.Network.Socket
370 , Streamly.Network.Socket
@@ -504,6 +505,9 @@ library
504 , Streamly.Internal.FileSystem.FDIO
505 , Streamly.Internal.FileSystem.FDIO
505 , Streamly.Internal.FileSystem.FD
506 , Streamly.Internal.FileSystem.FD
506
507
508+ -- streamly-console
509+ , Streamly.Internal.Console.Stdio
510+
507 -- streamly-network
511 -- streamly-network
508 , Streamly.Internal.Network.Socket
512 , Streamly.Internal.Network.Socket
509 , Streamly.Internal.Network.Inet.TCP
513 , Streamly.Internal.Network.Inet.TCP