@@ -9,29 +9,30 @@ module Database.Bolt.Value.Instances where
99import Database.Bolt.Value.Helpers
1010import Database.Bolt.Value.Type
1111
12- import Control.Monad (forM , replicateM )
13- import Control.Monad.Except (MonadError (.. ))
14- import Data.Binary (Binary (.. ), Put , decode , encode )
12+ import Control.Monad (forM , replicateM )
13+ import Control.Monad.Except (MonadError (.. ))
14+ import Data.Binary (Binary (.. ), Put , decode , encode )
1515import Data.Binary.Get
16- import Data.Binary.IEEE754 (doubleToWord , wordToDouble )
17- import Data.Binary.Put (putByteString , putWord16be , putWord32be , putWord64be ,
18- putWord8 )
19- import Data.ByteString (ByteString )
20- import qualified Data.ByteString as B
21- import Data.ByteString.Lazy (fromStrict , toStrict )
16+ import Data.Binary.IEEE754 (doubleToWord , wordToDouble )
17+ import Data.Binary.Put (putByteString , putWord16be , putWord32be , putWord64be ,
18+ putWord8 )
19+ import Data.ByteString (ByteString )
20+ import qualified Data.ByteString as B
21+ import Data.ByteString.Lazy (fromStrict , toStrict )
2222import Data.Int
23- import Data.Map.Strict (Map )
24- import qualified Data.Map.Strict as M
25- import Data.Text (Text )
26- import Data.Text.Encoding (decodeUtf8 , encodeUtf8 )
23+ import Data.Map.Strict (Map )
24+ import qualified Data.Map.Strict as M
25+ import Data.Text (Text )
26+ import Data.Text.Encoding (decodeUtf8 , encodeUtf8 )
2727import Data.Word
28+ import GHC.Stack (HasCallStack , callStack , prettyCallStack )
2829
2930instance BoltValue () where
3031 pack () = putWord8 nullCode
3132
3233 unpackT = getWord8 >>= unpackByMarker
3334 where unpackByMarker m | m == nullCode = pure ()
34- | otherwise = fail " expected null"
35+ | otherwise = failUnpack " null" m
3536
3637instance BoltValue Bool where
3738 pack True = putWord8 trueCode
@@ -40,7 +41,7 @@ instance BoltValue Bool where
4041 unpackT = getWord8 >>= unpackByMarker
4142 where unpackByMarker m | m == trueCode = pure True
4243 | m == falseCode = pure False
43- | otherwise = fail " expected bool"
44+ | otherwise = failUnpack " bool" m
4445
4546instance BoltValue Int where
4647 pack int | isTinyInt int = putWord8 $ fromIntegral int
@@ -56,14 +57,14 @@ instance BoltValue Int where
5657 | m == int16Code = toInt <$> getInt16be
5758 | m == int32Code = toInt <$> getInt32be
5859 | m == int64Code = toInt <$> getInt64be
59- | otherwise = fail " expected int"
60+ | otherwise = failUnpack " int" m
6061
6162instance BoltValue Double where
6263 pack dbl = putWord8 doubleCode >> putWord64be (doubleToWord dbl)
6364
6465 unpackT = getWord8 >>= unpackByMarker
6566 where unpackByMarker m | m == doubleCode = wordToDouble <$> getWord64be
66- | otherwise = fail " expected double"
67+ | otherwise = failUnpack " double" m
6768
6869instance BoltValue Text where
6970 pack txt = mkPackedCollection (B. length bs) pbs (textConst, text8Code, text16Code, text32Code)
@@ -75,7 +76,7 @@ instance BoltValue Text where
7576 | m == text8Code = toInt <$> getInt8 >>= unpackTextBySize
7677 | m == text16Code = toInt <$> getInt16be >>= unpackTextBySize
7778 | m == text32Code = toInt <$> getInt32be >>= unpackTextBySize
78- | otherwise = fail " expected text"
79+ | otherwise = failUnpack " text" m
7980 unpackTextBySize size = do str <- getByteString size
8081 pure $! decodeUtf8 str
8182
@@ -88,7 +89,7 @@ instance BoltValue a => BoltValue [a] where
8889 | m == list8Code = toInt <$> getInt8 >>= unpackListBySize
8990 | m == list16Code = toInt <$> getInt16be >>= unpackListBySize
9091 | m == list32Code = toInt <$> getInt32be >>= unpackListBySize
91- | otherwise = fail " expected list"
92+ | otherwise = failUnpack " list" m
9293 unpackListBySize size = forM [1 .. size] $ const unpackT
9394
9495instance BoltValue a => BoltValue (Map Text a ) where
@@ -98,10 +99,10 @@ instance BoltValue a => BoltValue (Map Text a) where
9899
99100 unpackT = getWord8 >>= unpackByMarker
100101 where unpackByMarker m | isTinyDict m = unpackDictBySize (getSize m)
101- | m == dict8Code = toInt <$> getInt16be >>= unpackDictBySize
102+ | m == dict8Code = toInt <$> getInt8 >>= unpackDictBySize
102103 | m == dict16Code = toInt <$> getInt16be >>= unpackDictBySize
103104 | m == dict32Code = toInt <$> getInt32be >>= unpackDictBySize
104- | otherwise = fail " expected dict"
105+ | otherwise = failUnpack " dict" m
105106 unpackDictBySize = (M. fromList <$> ) . unpackPairsBySize
106107 unpackPairsBySize size = forM [1 .. size] $ const $ do
107108 ! key <- unpackT
@@ -120,7 +121,7 @@ instance BoltValue Structure where
120121 where unpackByMarker m | isTinyStruct m = unpackStructureBySize (getSize m)
121122 | m == struct8Code = toInt <$> getInt8 >>= unpackStructureBySize
122123 | m == struct16Code = toInt <$> getInt16be >>= unpackStructureBySize
123- | otherwise = fail " expected structure"
124+ | otherwise = failUnpack " structure" m
124125 unpackStructureBySize size = Structure <$> getWord8 <*> replicateM size unpackT
125126
126127instance BoltValue Value where
@@ -142,7 +143,7 @@ instance BoltValue Value where
142143 | isList m = L <$> unpackT
143144 | isDict m = M <$> unpackT
144145 | isStruct m = S <$> unpackT
145- | otherwise = fail " not value"
146+ | otherwise = failUnpack " value" m
146147
147148-- = Structure instances for Neo4j structures
148149
@@ -207,3 +208,10 @@ size4 = 2^(4 :: Int)
207208size8 = 2 ^ (8 :: Int )
208209size16 = 2 ^ (16 :: Int )
209210size32 = 2 ^ (32 :: Int )
211+
212+ failUnpack :: (HasCallStack , MonadFail m ) => String -> Word8 -> m a
213+ failUnpack expected got = fail $
214+ " expected " <> expected <> " , got: " <> show got
215+ <> (if null cs then " " else " \n " <> cs)
216+ where
217+ cs = prettyCallStack callStack
0 commit comments