{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} module Main (main) where import qualified Codec.Compression.LZ4.Conduit as LZ4F import Control.Applicative (optional) import Control.Monad.Trans.Resource (runResourceT) import Data.Conduit import qualified Data.Conduit.Binary as CB import Data.Monoid ((<>)) import Data.Text (Text) import qualified Data.Text as T import Options.Applicative (Parser, argument, str, metavar, long, short) import qualified Options.Applicative as Opts import System.IO (stdin, stdout) -- | Command line arguments of this program. data CLIArgs = CLIArgs { m'inputFile :: Maybe Text , m'outputFile :: Maybe Text , decompress :: Bool } deriving (Eq, Ord, Show) cliArgsParser :: Parser CLIArgs cliArgsParser = CLIArgs <$> optional (T.pack <$> argument str (metavar "INPUT_FILE")) <*> optional (T.pack <$> argument str (metavar "OUTPUT-FILE")) <*> Opts.switch (long "decompress" <> short 'd') -- | Parses the command line arguments for this program. parseArgs :: IO CLIArgs parseArgs = Opts.execParser $ Opts.info (Opts.helper <*> cliArgsParser) (Opts.fullDesc <> Opts.progDesc "Compress or decompress .lz4 files") main :: IO () main = do CLIArgs { m'inputFile , m'outputFile , decompress } <- parseArgs let source = case m'inputFile of Nothing -> CB.sourceHandle stdin Just "-" -> CB.sourceHandle stdin Just path -> CB.sourceFile (T.unpack path) let sink = case m'outputFile of Nothing -> CB.sinkHandle stdout Just "-" -> CB.sinkHandle stdout Just path -> CB.sinkFile (T.unpack path) let compressOrDecompress | decompress = LZ4F.decompress | otherwise = LZ4F.compress runResourceT $ runConduit $ source .| compressOrDecompress .| sink