packages feed

lz4-frame-conduit-0.1.0.0: app/Main.hs

{-# 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