module Text.Search.Sphinx.Get where
import Data.Binary.Get
import Data.Binary.IEEE754
import Data.Int (Int64)
import Prelude hiding (readList)
import Data.ByteString.Lazy hiding (pack, length, map, groupBy)
import Control.Monad
import qualified Text.Search.Sphinx.Types as T
import Data.Maybe (isJust, fromJust)
getNum :: Get Int
getNum = getWord32be >>= return . fromEnum
getFloat :: Get Float
getFloat = getFloat32be
getNum64 :: Get Int64
getNum64 = getWord64be >>= return . fromIntegral
readList f = do num <- getNum
num `times` f
times = replicateM
getStr = do len <- getNum
getLazyByteString (fromIntegral len)
getResult :: Get (T.SingleResult)
getResult = do
statusNum <- getNum
case T.toQueryStatus statusNum of
T.QueryERROR n -> do e <- getStr
return $ T.QueryError statusNum e
T.QueryOK -> getResultOk >>= return . T.QueryOk
T.QueryWARNING -> do w <- getStr
getResultOk >>= return . (T.QueryWarning w)
where
getResultOk = do
fields <- readList getStr
attrs <- readList readAttrPair
matchCount <- getNum
id64 <- getNum
matches <- matchCount `times` readMatch (id64 > 0) (map snd attrs)
[total, totalFound, time, numWords] <- 4 `times` getNum
wrds <- numWords `times` readWord
return $ T.QueryResult matches total totalFound wrds (map fst attrs)
readWord = do s <- getStr
[doc, hits] <- 2 `times` getNum
return (s, doc, hits)
readMatch isId64 attrs = do
doc <- if isId64 then getNum64 else (getNum >>= return . fromIntegral)
weight <- getNum
matchAttrs <- mapM readAttr attrs
return $ T.Match doc weight matchAttrs
where
readAttr (T.AttrTMulti attr) = (readList (readAttr attr)) >>= return . T.AttrMulti
readAttr T.AttrTBigInt = getNum64 >>= return . T.AttrBigInt
readAttr T.AttrTString = getStr >>= return . T.AttrString
readAttr T.AttrTUInt = getNum >>= return . T.AttrUInt
readAttr T.AttrTFloat = getFloat >>= return . T.AttrFloat
readAttr _ = getNum >>= return . T.AttrUInt
readAttrPair = do
s <- getStr
t <- getNum
return (s, toEnum t)
readHeader = runGet $ do status <- getWord16be
version <- getWord16be
length <- getWord32be
return (T.toStatus $ fromIntegral status, version, length)