3
3
module Database.PostgreSQL.Protocol.Decoders
4
4
(
5
5
-- * High-lever decoder
6
- decodeNextServerMessage
6
+ decodeNextServerMessage
7
7
-- * Decoders
8
8
, decodeAuthResponse
9
9
, decodeHeader
@@ -14,26 +14,18 @@ module Database.PostgreSQL.Protocol.Decoders
14
14
, parseErrorDesc
15
15
) where
16
16
17
- import Control.Applicative
18
- import Control.Monad
19
17
import Data.Monoid ((<>) )
20
18
import Data.Maybe (fromMaybe )
21
19
import Data.Char (chr )
22
- import Data.Word
23
- import Foreign
20
+ import Data.Word (Word8 , Word16 , Word32 )
24
21
import Text.Read (readMaybe )
25
22
import qualified Data.Vector as V
26
23
import qualified Data.ByteString as B
27
- import qualified Data.ByteString.Unsafe as B
28
- import qualified Data.ByteString.Lazy as BL
29
- import qualified Data.ByteString.Lazy.Internal as BL
30
24
import Data.ByteString.Char8 as BS (readInteger , readInt , unpack , pack )
31
25
import qualified Data.HashMap.Strict as HM
32
26
33
27
import Database.PostgreSQL.Protocol.Types
34
28
import Database.PostgreSQL.Protocol.Store.Decode
35
- import Database.PostgreSQL.Protocol.Utils
36
-
37
29
38
30
-- | Parses and dispatches all server messages except `DataRow`.
39
31
decodeNextServerMessage
@@ -46,7 +38,7 @@ decodeNextServerMessage bs readMoreAction = go Nothing bs
46
38
where
47
39
-- Parse header
48
40
go Nothing bs
49
- | B. length bs < 5 = readMoreAndGo Nothing bs
41
+ | B. length bs < headerSize = readMoreAndGo Nothing bs
50
42
| otherwise = let (rest, h) = runDecode decodeHeader bs
51
43
in go (Just h) rest
52
44
-- Parse body
@@ -57,13 +49,15 @@ decodeNextServerMessage bs readMoreAction = go Nothing bs
57
49
{-# INLINE readMoreAndGo #-}
58
50
readMoreAndGo h = (go h =<< ) . readMoreAction
59
51
52
+ --------------------------------
53
+ -- Protocol decoders
54
+
60
55
decodeAuthResponse :: Decode AuthResponse
61
56
decodeAuthResponse = do
62
- c <- getWord8
63
- len <- getInt32BE
57
+ Header c len <- decodeHeader
64
58
case chr $ fromIntegral c of
65
59
' E' -> AuthErrorResponse <$>
66
- (getByteString ( fromIntegral $ len - 4 ) >>=
60
+ (getByteString len >>=
67
61
eitherToDecode . parseErrorDesc)
68
62
' R' -> do
69
63
rType <- getInt32BE
@@ -73,8 +67,7 @@ decodeAuthResponse = do
73
67
5 -> AuthenticationMD5Password . MD5Salt <$> getByteString 4
74
68
7 -> pure AuthenticationGSS
75
69
9 -> pure AuthenticationSSPI
76
- 8 -> AuthenticationGSSContinue <$>
77
- getByteString (fromIntegral $ len - 8 )
70
+ 8 -> AuthenticationGSSContinue <$> getByteString (len - 4 )
78
71
_ -> fail " Unknown authentication response"
79
72
_ -> fail " Invalid auth response"
80
73
@@ -115,14 +108,6 @@ decodeServerMessage (Header c len) = case chr $ fromIntegral c of
115
108
rowsCount <- fromIntegral <$> getInt16BE
116
109
RowDescription <$> V. replicateM rowsCount decodeFieldDescription
117
110
118
- -- | Decodes a single data value. Length `-1` indicates a NULL column value.
119
- -- No value bytes follow in the NULL case.
120
- decodeValue :: Decode (Maybe B. ByteString )
121
- decodeValue = getInt32BE >>= \ n ->
122
- if n == - 1
123
- then pure Nothing
124
- else Just <$> getByteString (fromIntegral n)
125
-
126
111
decodeTransactionStatus :: Decode TransactionStatus
127
112
decodeTransactionStatus = getWord8 >>= \ t ->
128
113
case chr $ fromIntegral t of
@@ -154,7 +139,8 @@ decodeFormat = getInt16BE >>= \f ->
154
139
1 -> pure Binary
155
140
_ -> fail " Unknown field format"
156
141
157
- -- Parser that just work with B.ByteString, not Decode type
142
+ -----------------------------
143
+ -- Helper parsers that work with B.ByteString, not Decode type
158
144
159
145
-- Helper to parse, not used by decoder itself
160
146
parseServerVersion :: B. ByteString -> Either B. ByteString ServerVersion
@@ -288,6 +274,7 @@ parseNoticeDesc s = do
288
274
" is not presented in NoticeResponse message" )
289
275
Right . HM. lookup c
290
276
277
+ -- | Helper to lift Either in Decode
291
278
eitherToDecode :: Either B. ByteString a -> Decode a
292
279
eitherToDecode = either (fail . BS. unpack) pure
293
280
0 commit comments