on master help sign in
decodeFileEither
8b565b3Michael Snoyman
Data/Yaml.hs+29−1
@@ -52,6 +52,7 @@ module Data.Yaml
52 -- ** Better error information
52 -- ** Better error information
53 , decodeEither
53 , decodeEither
54 , decodeEither'
54 , decodeEither'
55+ , decodeFileEither
55 -- ** More control over decoding
56 -- ** More control over decoding
56 , decodeHelper
57 , decodeHelper
57 ) where
58 ) where
@@ -68,7 +69,7 @@ import Data.ByteString (ByteString)
68import qualified Data.ByteString.Char8 as S8
69import qualified Data.ByteString.Char8 as S8
69import qualified Data.Map as Map
70import qualified Data.Map as Map
70import System.IO.Unsafe (unsafePerformIO)
71import System.IO.Unsafe (unsafePerformIO)
71−import Control.Exception (try, throwIO, fromException, Exception)
72+import Control.Exception (try, throwIO, fromException, Exception, SomeException, AsyncException)
72import Control.Monad.Trans.State
73import Control.Monad.Trans.State
73import qualified Data.Conduit as C
74import qualified Data.Conduit as C
74import qualified Data.Conduit.List as CL
75import qualified Data.Conduit.List as CL
@@ -142,6 +143,7 @@ data ParseException = NonScalarKey
142 }
143 }
143 | InvalidYaml (Maybe YamlException)
144 | InvalidYaml (Maybe YamlException)
144 | AesonException String
145 | AesonException String
146+ | OtherParseException SomeException
145 deriving (Show, Typeable)
147 deriving (Show, Typeable)
146instance Exception ParseException
148instance Exception ParseException
147
149
@@ -278,6 +280,32 @@ decodeFile :: FromJSON a
278 -> IO (Maybe a)
280 -> IO (Maybe a)
279decodeFile fp = decodeHelper (Y.decodeFile fp) >>= either throwIO (return . either (const Nothing) id)
281decodeFile fp = decodeHelper (Y.decodeFile fp) >>= either throwIO (return . either (const Nothing) id)
280
282
283+-- | A version of 'decodeFile' which should not throw runtime exceptions.
284+--
285+-- Since 0.8.4
286+decodeFileEither
287+ :: FromJSON a
288+ => FilePath
289+ -> IO (Either ParseException a)
290+decodeFileEither fp = do
291+ x <- try $ C.runResourceT $ flip evalStateT Map.empty $ Y.decodeFile fp C.$$ parse
292+ case x of
293+ Left e
294+ | Just pe <- fromException e -> return $ Left pe
295+ | Just ye <- fromException e -> return $ Left $ InvalidYaml $ Just (ye :: YamlException)
296+ | shouldBeCaught e -> return $ Left $ OtherParseException e
297+ | otherwise -> throwIO e
298+ Right y ->
299+ return $ case parseEither parseJSON y of
300+ Left s -> Left $ AesonException s
301+ Right v -> Right v
302+ where
303+ -- FIXME this function needs more thought
304+ shouldBeCaught e
305+ | Just (_ :: AsyncException) <- fromException e = False
306+ -- Would be nice... | Just (_ :: Timeout) <- fromException e = False
307+ | otherwise = True
308+
281decodeEither :: FromJSON a => ByteString -> Either String a
309decodeEither :: FromJSON a => ByteString -> Either String a
282decodeEither bs = unsafePerformIO
310decodeEither bs = unsafePerformIO
283 $ fmap (either (Left . show) id)
311 $ fmap (either (Left . show) id)
yaml.cabal+1−1
@@ -1,5 +1,5 @@
1name: yaml
1name: yaml
2−version: 0.8.3
2+version: 0.8.4
3license: BSD3
3license: BSD3
4license-file: LICENSE
4license-file: LICENSE
5author: Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>,Kirill Simonov
5author: Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>,Kirill Simonov