module PbAnalyser
( getNext
) where
import Data.List
import Data.Maybe
import Data.Either.Combinators
import Control.Monad.IO.Class
import Control.Monad.Trans.Either
import Data.Text (Text, pack, unpack)
import qualified Data.Text.IO (readFile)
import qualified Text.Parsec as Parsec
import Proto
import ProtoParser
parse :: FilePath -> EitherT Parsec.ParseError IO Proto
parse fileName = do
file <- liftIO $ Data.Text.IO.readFile fileName
EitherT . return $ Parsec.parse protoParser "" file
getNext :: Text -> FilePath -> EitherT String IO Integer
getNext messageName fileName = do
proto <- mapLeftEitherT show $ parse fileName
let matchingMessages = concatMap (foldMap (getMatchingProtoObjs messageName)) proto
case matchingMessages of
[] -> fail $ "No proto-objs found with name " ++ unpack messageName
(message:[]) -> right $ getNext' message
_ -> fail $ "Multiple proto-objs found with name " ++ unpack messageName
where
getNext' :: Message -> Integer
getNext' (Message _ fields)
= maybe (succ . maximum $ fieldNums) fst
. find (uncurry (/=))
$ zip [1..] fieldNums
where
fieldNums :: [Integer]
fieldNums = sort . map value $ fields
mapLeftEitherT :: Monad m => (l -> l') -> EitherT l m r -> EitherT l' m r
mapLeftEitherT getMatchingProtoObjs
= EitherT
. fmap (mapLeft getMatchingProtoObjs)
. runEitherT
getMatchingProtoObjs :: Text -> Message -> [Message]
getMatchingProtoObjs query m@(Message name _)
| name == query = [m]
| otherwise = []