io-streams-1.1.4.3: src/System/IO/Streams/Debug.hs
{-# LANGUAGE OverloadedStrings #-}
-- | Convenience module for debugging streams. Provides stream transformers
-- that wrap 'InputStream's and 'OutputStream's, sending a description of all
-- data to an 'OutputStream' for debugging.
module System.IO.Streams.Debug
( -- * Debuggers
debugInput
, debugOutput
, debugInputBS
, debugOutputBS
) where
------------------------------------------------------------------------------
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as S
------------------------------------------------------------------------------
import System.IO.Streams.Internal (InputStream (..), OutputStream)
import qualified System.IO.Streams.Internal as Streams
------------------------------------------------------------------------------
debugInput ::
(a -> ByteString) -- ^ function to convert stream elements to
-- 'ByteString'
-> ByteString -- ^ name of this debug stream, will be
-- prepended to debug output
-> OutputStream ByteString -- ^ stream the debug info will be sent to
-> InputStream a -- ^ input stream
-> IO (InputStream a)
debugInput toBS name debugStream inputStream = return $ InputStream produce pb
where
produce = do
m <- Streams.read inputStream
Streams.write (Just $! describe m) debugStream
return m
pb c = do
let s = S.concat [name, ": pushback: ", toBS c, "\n"]
Streams.write (Just s) debugStream
Streams.unRead c inputStream
describe m = S.concat [name, ": got ", describeChunk m, "\n"]
describeChunk Nothing = "EOF"
describeChunk (Just s) = S.concat [ "chunk: ", toBS s ]
------------------------------------------------------------------------------
debugInputBS ::
ByteString -- ^ name of this debug stream, will be
-- prepended to debug output
-> OutputStream ByteString -- ^ stream the debug info will be sent to
-> InputStream ByteString -- ^ input stream
-> IO (InputStream ByteString)
debugInputBS = debugInput condense
------------------------------------------------------------------------------
debugOutput :: (a -> ByteString) -- ^ function to convert stream
-- elements to 'ByteString'
-> ByteString -- ^ name of this debug stream, will be
-- prepended to debug output
-> OutputStream ByteString -- ^ debug stream
-> OutputStream a -- ^ output stream
-> IO (OutputStream a)
debugOutput toBS name debugStream outputStream =
Streams.makeOutputStream f
where
f m = do
Streams.write (Just $ describe m) debugStream
Streams.write m outputStream
describe m = S.concat [name, ": got ", describeChunk m, "\n"]
describeChunk Nothing = "EOF"
describeChunk (Just s) = S.concat [ "chunk: ", toBS s]
------------------------------------------------------------------------------
debugOutputBS ::
ByteString -- ^ name of this debug stream, will be
-- prepended to debug output
-> OutputStream ByteString -- ^ stream the debug info will be sent to
-> OutputStream ByteString -- ^ output stream
-> IO (OutputStream ByteString)
debugOutputBS = debugOutput condense
------------------------------------------------------------------------------
condense :: ByteString -> ByteString
condense s | l < 32 = S.concat [ "\"", s, "\"" ]
| otherwise = S.concat [
"\""
, S.take k s
, " ... "
, S.drop (l - k) s
, "\" ("
, S.pack (show l)
, " bytes)"
]
where
k = 14
l = S.length s