packages feed

hw-dsv-0.1.0.0: app/App/Commands/CreateIndex.hs

{-# LANGUAGE BangPatterns #-}

module App.Commands.CreateIndex
  ( cmdCreateIndex
  ) where

import App.Char
import App.Commands.Options.Type
import Control.Lens
import Control.Monad
import Data.Semigroup            ((<>))
import Options.Applicative       hiding (columns)

import qualified App.IO                                 as IO
import qualified App.Lens                               as L
import qualified Data.ByteString.Builder                as B
import qualified Data.Vector.Storable                   as DVS
import qualified HaskellWorks.Data.Dsv.Lazy.Cursor      as SVL
import qualified HaskellWorks.Data.Dsv.Lazy.Cursor.Type as SVL
import qualified System.IO                              as IO

runCreateIndex :: CreateIndexOptions -> IO ()
runCreateIndex opts = do
  let !filePath   = opts ^. L.filePath
  let !delimiter  = opts ^. L.delimiter

  !bs <- IO.readInputFile filePath

  let !cursor   = SVL.makeCursor delimiter bs
  let !markers  = cursor & SVL.dsvCursorMarkers
  let !newlines = cursor & SVL.dsvCursorNewlines

  hOutMarkers <- IO.openFile (filePath ++ ".markers.idx") IO.WriteMode
  forM_ (markers >>= DVS.toList) $ \w -> do
    B.hPutBuilder hOutMarkers (B.word64LE w)
  IO.hClose hOutMarkers

  hOutNewlines <- IO.openFile (filePath ++ ".newlines.idx") IO.WriteMode
  forM_ (newlines >>= DVS.toList) $ \w -> do
    B.hPutBuilder hOutNewlines (B.word64LE w)
  IO.hClose hOutNewlines

  return ()

optsCreateIndex :: Parser CreateIndexOptions
optsCreateIndex = CreateIndexOptions
  <$> strOption
        (   long "input"
        <>  short 'i'
        <>  help "Input DSV file"
        <>  metavar "STRING"
        )
  <*> option readChar
        (   long "input-delimiter"
        <>  short 'd'
        <>  help "DSV delimiter"
        <>  metavar "CHAR"
        )

cmdCreateIndex :: Mod CommandFields (IO ())
cmdCreateIndex = command "create-index"  $ flip info idm $ runCreateIndex <$> optsCreateIndex