{-# LANGUAGE GADTs #-} {-# LANGUAGE RankNTypes #-} -- | @since 2.2.0 module Distribution.Utils.IOData ( -- * 'IOData' & 'IODataMode' type IOData (..) , IODataMode (..) , KnownIODataMode (..) , withIOData , null , hPutContents ) where import qualified Data.ByteString.Lazy as LBS import Distribution.Compat.Prelude hiding (null) import qualified Prelude import qualified System.IO -- | Represents either textual or binary data passed via I/O functions -- which support binary/text mode -- -- @since 2.2 data IOData = IODataText String -- ^ How Text gets encoded is usually locale-dependent. | IODataBinary LBS.ByteString -- ^ Raw binary which gets read/written in binary mode. withIOData :: IOData -> (forall mode. IODataMode mode -> mode -> r) -> r withIOData (IODataText str) k = k IODataModeText str withIOData (IODataBinary lbs) k = k IODataModeBinary lbs -- | Test whether 'IOData' is empty null :: IOData -> Bool null (IODataText s) = Prelude.null s null (IODataBinary b) = LBS.null b instance NFData IOData where rnf (IODataText s) = rnf s rnf (IODataBinary lbs) = rnf lbs -- | @since 2.2 class NFData mode => KnownIODataMode mode where -- | 'IOData' Wrapper for 'System.IO.hGetContents' -- -- __Note__: This operation uses lazy I/O. Use 'NFData' to force all -- data to be read and consequently the internal file handle to be -- closed. -- hGetIODataContents :: System.IO.Handle -> Prelude.IO mode toIOData :: mode -> IOData iodataMode :: IODataMode mode -- | @since 3.2 data IODataMode mode where IODataModeText :: IODataMode String IODataModeBinary :: IODataMode LBS.ByteString instance a ~ Char => KnownIODataMode [a] where hGetIODataContents h = do System.IO.hSetBinaryMode h False System.IO.hGetContents h toIOData = IODataText iodataMode = IODataModeText instance KnownIODataMode LBS.ByteString where hGetIODataContents h = do System.IO.hSetBinaryMode h True LBS.hGetContents h toIOData = IODataBinary iodataMode = IODataModeBinary -- | 'IOData' Wrapper for 'System.IO.hPutStr' and 'System.IO.hClose' -- -- This is the dual operation ot 'hGetIODataContents', -- and consequently the handle is closed with `hClose`. -- -- /Note:/ this performs lazy-IO. -- -- @since 2.2 hPutContents :: System.IO.Handle -> IOData -> Prelude.IO () hPutContents h (IODataText c) = do System.IO.hSetBinaryMode h False System.IO.hPutStr h c System.IO.hClose h hPutContents h (IODataBinary c) = do System.IO.hSetBinaryMode h True LBS.hPutStr h c System.IO.hClose h