module Bio.MMTF.Decode.MessagePack where import Data.ByteString.Lazy (ByteString, fromStrict) import Data.Map.Strict (Map, fromList) import qualified Data.Map.Strict as M (lookup) import Data.MessagePack import Data.Monoid ((<>)) import Data.Text (Text) import qualified Data.Text as T (unpack) transformObjectMap :: Monad m => Object -> m (Map Text Object) transformObjectMap (ObjectMap kv) = let mkPair :: Monad m => (Object, Object) -> m (Text, Object) mkPair (ObjectStr txt, v) = pure (txt, v) mkPair _ = fail "Non-string key" in fromList <$> traverse mkPair kv transformObjectMap _ = fail "Wrong MessagePack MMTF format" atP :: Monad m => Map Text Object -> Text -> (Text -> Object -> m a) -> m a atP m k conv = case M.lookup k m of Just x -> conv k x Nothing -> fail $ "Required field '" ++ uk ++ "' was not found" where uk = T.unpack k atPM :: Monad m => Map Text Object -> Text -> (Text -> Object -> m a) -> m (Maybe a) atPM m k conv = traverse (conv k) $ M.lookup k m atPMD :: Monad m => Map Text Object -> Text -> (Text -> Object -> m a) -> a -> m a atPMD m k conv def = do x <- atPM m k conv case x of Just r -> pure r Nothing -> pure def asStr :: Monad m => Text -> Object -> m Text asStr _ (ObjectStr s) = pure s asStr m _ = fail $ T.unpack m <> ": not a string data" asChar :: Monad m => Text -> Object -> m Char asChar m = (head . T.unpack <$>) . asStr m asInt :: (Monad m, Integral a) => Text -> Object -> m a asInt _ (ObjectInt i) = pure (fromIntegral i) asInt _ (ObjectWord w) = pure (fromIntegral w) asInt m _ = fail $ T.unpack m <> ": not an int data" asFloat :: Monad m => Text -> Object -> m Float asFloat _ (ObjectFloat f) = pure f asFloat _ (ObjectDouble f) = pure (realToFrac f) asFloat m _ = fail $ T.unpack m <> ": not a float data" asIntList :: (Monad m, Integral a) => Text -> Object -> m [a] asIntList m (ObjectArray l) = traverse (asInt m) l asIntList m _ = fail $ T.unpack m <> ": not an array of ints data" asStrList :: Monad m => Text -> Object -> m [Text] asStrList m (ObjectArray l) = traverse (asStr m) l asStrList m _ = fail $ T.unpack m <> ": not an array of string data" asFloatList :: Monad m => Text -> Object -> m [Float] asFloatList m (ObjectArray l) = traverse (asFloat m) l asFloatList m _ = fail $ T.unpack m <> ": not an array of float data" asObjectList :: Monad m => Text -> Object -> m [Object] asObjectList _ (ObjectArray l) = pure l asObjectList m _ = fail $ T.unpack m <> ": not an array data" asBinary :: Monad m => Text -> Object -> m ByteString asBinary _ (ObjectBin bs) = pure (fromStrict bs) asBinary m _ = fail $ T.unpack m <> ": not a binary data"