{-# LANGUAGE TupleSections, RecordWildCards, ScopedTypeVariables, PatternGuards, DeriveDataTypeable, GADTs #-}
module Output.Items(writeItems, lookupItem, listItems) where
import Control.Monad
import Data.List.Extra
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy.Char8 as LBS
import qualified Data.ByteString.Lazy.UTF8 as UTF8
import qualified Codec.Compression.GZip as GZip
import General.Str
import Input.Item
import General.Util
import General.Store
import General.Conduit
data Items a where Items :: Items BS.ByteString deriving Typeable
outputItem :: Target -> [String]
outputItem Target{..} =
[if null targetURL then "." else targetURL
,maybe "." (joinPair " ") targetPackage
,maybe "." (joinPair " ") targetModule
,if null targetType then "." else targetType
,targetItem] ++
replace [""] ["."] (lines targetDocs)
inputItem :: [String] -> Target
inputItem (url:pkg:modu:typ:self:docs) = targetExpandURL $
Target (if url == "." then "" else url) (f pkg) (f modu) (if typ == "." then "" else typ) self (unlines $ replace ["."] [""] docs)
where
f "." = Nothing
f x = Just $ word1 x
writeItems :: StoreWrite -> (ConduitM (Maybe Target, item) (Maybe TargetId, item) IO () -> IO a) -> IO a
writeItems store act = act $ do
void $ (\f -> mapAccumMC f 0) $ \pos (target, item) -> case target of
Nothing -> return (pos, (Nothing, item))
Just target -> do
let bs = LBS.toStrict $ GZip.compress $ lbstrPack $ unlines $ outputItem target
liftIO $ do
storeWritePart store Items $ intToBS $ BS.length bs
storeWritePart store Items bs
let pos2 = pos + fromIntegral (intSize + BS.length bs)
return (pos2, (Just $ TargetId pos, item))
listItems :: StoreRead -> [Target]
listItems store = unfoldr f $ storeRead store Items
where
f x | BS.null x = Nothing
| (n,x) <- BS.splitAt intSize x
, n <- intFromBS n
, (this,x) <- BS.splitAt n x
= Just (inputItem $ lines $ UTF8.toString $ GZip.decompress $ LBS.fromChunks [this], x)
lookupItem :: StoreRead -> (TargetId -> Target)
lookupItem store =
let x = storeRead store Items
in \(TargetId i) ->
let i2 = fromIntegral i
n = intFromBS $ BS.take intSize $ BS.drop i2 x
in inputItem $ lines $ UTF8.toString $ GZip.decompress $ LBS.fromChunks $ return $ BS.take n $ BS.drop (i2 + intSize) x