hw-dump-0.0.0.1: app/App/Commands/Bits.hs
{-# LANGUAGE ScopedTypeVariables #-}
module App.Commands.Bits
( cmdBits
) where
import App.Commands.Options.Type
import Control.Lens
import Control.Monad
import Data.Char (isAscii, isPrint)
import Data.List (transpose)
import Data.Semigroup ((<>))
import HaskellWorks.Data.Bits.BitShow
import Numeric (showHex)
import Options.Applicative hiding (columns)
import qualified App.Commands.Options.Lens as L
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Lazy.Char8 as C8
import qualified System.IO as IO
{-# ANN module ("HLint: ignore Redundant do" :: String) #-}
{-# ANN module ("HLint: ignore Redundant return" :: String) #-}
lazyByteStringChunks :: Int -> LBS.ByteString -> [LBS.ByteString]
lazyByteStringChunks n bs = case LBS.splitAt (fromIntegral n) bs of
(lbs, rbs) -> if LBS.length rbs > 0
then lbs:lazyByteStringChunks n rbs
else if LBS.length lbs > 0
then [lbs]
else []
zap :: [a] -> [[b]] -> [(a, [b])]
zap (a:as) (b:bs) = (a, b):(zap as bs)
zap (a:as) _ = (a, []):(zap as [])
zap _ _ = []
isAsciiPrintable :: Char -> Bool
isAsciiPrintable c = isPrint c && isAscii c
maskNonAsciiPrintable :: Char -> Char
maskNonAsciiPrintable c = if isAsciiPrintable c then c else '.'
runBits :: BitsOptions -> IO ()
runBits opts = do
let file = opts ^. L.file
let bitFiles = opts^. L.bitFiles
chunkedContents <- lazyByteStringChunks 64 <$> LBS.readFile file
chunkedBitContents <- forM bitFiles $ (lazyByteStringChunks 8 <$>) . LBS.readFile
forM_ (zap (zip [0..] chunkedContents) (transpose chunkedBitContents)) $ \((i :: Int, as), bss) -> do
IO.putStr (reverse (take 8 (reverse ((("00000000" ++) . showHex i) ""))))
IO.putStr " "
let css = lazyByteStringChunks 8 as
forM_ css $ \cs -> do
IO.putStr " "
IO.putStr (maskNonAsciiPrintable <$> C8.unpack cs)
IO.putStrLn ""
forM_ bss $ \bs -> do
IO.putStr " "
forM_ (zip css (LBS.unpack bs)) $ \(cs, b) -> do
IO.putStr " "
IO.putStr $ take (fromIntegral (LBS.length cs)) (bitShow b)
IO.putStrLn ""
IO.putStrLn ""
return ()
return ()
optsBits :: Parser BitsOptions
optsBits = BitsOptions
<$> strOption
( long "file"
<> help "Source file"
<> metavar "FILE"
)
<*> many
( strOption
( long "bit-file"
<> help "Bit file"
<> metavar "FILE"
)
)
cmdBits :: Mod CommandFields (IO ())
cmdBits = command "bits" $ flip info idm $ runBits <$> optsBits