Skip to content

Commit 70aabf0

Browse files
committed
repace Parsec with Attoparsec
1 parent aa8b9e5 commit 70aabf0

File tree

1 file changed

+53
-96
lines changed

1 file changed

+53
-96
lines changed

Web/SocketIO/Protocol.hs

Lines changed: 53 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,21 @@ import Web.SocketIO.Types
1010
--------------------------------------------------------------------------------
1111
import Control.Applicative ((<$>), (<*>))
1212
import Data.Aeson
13-
import qualified Data.ByteString.Lazy as B
1413
import qualified Data.ByteString.Lazy as BL
1514
--import Text.Parsec
1615
--import Text.Parsec.ByteString.Lazy
1716
import Data.Attoparsec.ByteString.Lazy
17+
import Data.Attoparsec.ByteString.Char8 (digit, decimal)
1818
import Prelude hiding (take)
1919

20-
21-
parseMessage = undefined
22-
--parsePath = undefined
2320
--------------------------------------------------------------------------------
2421
-- | Parse raw ByteString to Messages
2522
parseFramedMessage :: BL.ByteString -> Framed Message
2623
parseFramedMessage input = if isSingleton
2724
then Framed $ [parseMessage' input]
2825
else Framed $ map parseMessage' splitted
2926
where splitted = split input
30-
parseMessage' x = case (eitherResult . parse parseMessage) x of
27+
parseMessage' x = case (eitherResult . parse messageParser) x of
3128
Left _ -> MsgNoop
3229
Right a -> a
3330
isSingleton = not (BL.null input) && BL.head input /= 239
@@ -44,114 +41,74 @@ split str = map (BL.drop 2) . skipOddIndexed True . filter isDelimiter . BL.spli
4441

4542
----------------------------------------------------------------------------------
4643
---- | Message, not framed
47-
--parseMessage :: Parser Message
48-
--parseMessage = do
49-
-- n <- digit
50-
-- case n of
51-
-- '0' -> (parseID >> parseEndpoint >>= return . MsgDisconnect)
52-
-- <|> ( return $ MsgDisconnect NoEndpoint)
53-
-- '1' -> (parseID >> parseEndpoint >>= return . MsgConnect)
54-
-- <|> ( return $ MsgConnect NoEndpoint)
55-
-- '2' -> return MsgHeartbeat
56-
-- '3' -> parseRegularMessage Msg
57-
-- '4' -> parseRegularMessage MsgJSON
58-
-- '5' -> MsgEvent <$> parseID
59-
-- <*> parseEndpoint
60-
-- <*> parseEvent
61-
-- '6' -> try (do
62-
-- string ":::"
63-
-- n' <- read <$> number
64-
-- char '+'
65-
-- d <- fromString <$> text
66-
-- return $ MsgACK (ID n') (Data d)
67-
-- ) <|> (do
68-
-- string ":::"
69-
-- n' <- read <$> number
70-
-- return $ MsgACK (ID n') NoData
71-
-- )
72-
-- '7' -> colon >> MsgError <$> parseEndpoint <*> parseData
73-
-- '8' -> return $ MsgNoop
74-
-- _ -> return $ MsgNoop
75-
-- where parseRegularMessage ctr = ctr <$> parseID
76-
-- <*> parseEndpoint
77-
-- <*> parseData
78-
79-
----------------------------------------------------------------------------------
80-
--endpoint :: Parser String
81-
--endpoint = many1 $ satisfy (/= ':')
82-
83-
----------------------------------------------------------------------------------
84-
--number :: Parser String
85-
--number = many1 digit
86-
87-
----------------------------------------------------------------------------------
88-
--colon :: Parser Char
89-
--colon = char ':'
90-
91-
----------------------------------------------------------------------------------
92-
--parseID :: Parser ID
93-
--parseID = try (colon >> number >>= plus >>= return . IDPlus . read)
94-
-- <|> try (colon >> number >>= return . ID . read)
95-
-- <|> (colon >> return NoID)
96-
-- where plus n = char '+' >> return n
97-
98-
----------------------------------------------------------------------------------
99-
--parseEndpoint :: Parser Endpoint
100-
--parseEndpoint = try (colon >> fromString <$> endpoint >>= return . Endpoint)
101-
-- <|> (colon >> return NoEndpoint)
102-
103-
----------------------------------------------------------------------------------
104-
--parseData :: Parser Data
105-
--parseData = try (colon >> text >>= return . Data . fromString)
106-
-- <|> (colon >> return NoData)
107-
108-
----------------------------------------------------------------------------------
109-
--parseEvent :: Parser Event
110-
--parseEvent = try (do
111-
-- colon
112-
-- t <- text
113-
-- case decode (fromString t) of
114-
-- Just e -> return e
115-
-- Nothing -> return NoEvent
116-
-- )
117-
-- <|> (colon >> return NoEvent)
118-
119-
120-
----------------------------------------------------------------------------------
121-
---- | Slashes as delimiters
122-
--textWithoutSlash :: Parser String
123-
--textWithoutSlash = many1 $ satisfy (/= '/')
44+
messageParser :: Parser Message
45+
messageParser = do
46+
n <- digit
47+
case n of
48+
'0' -> choice
49+
[ idParser >> endpointParser >>= return . MsgDisconnect
50+
, return $ MsgDisconnect NoEndpoint
51+
]
52+
'1' -> choice
53+
[ idParser >> endpointParser >>= return . MsgConnect
54+
, return $ MsgConnect NoEndpoint
55+
]
56+
'2' -> return MsgHeartbeat
57+
'3' -> Msg <$> idParser
58+
<*> endpointParser
59+
<*> dataParser
60+
'4' -> MsgJSON <$> idParser
61+
<*> endpointParser
62+
<*> dataParser
63+
'5' -> MsgEvent <$> idParser
64+
<*> endpointParser
65+
<*> eventParser
66+
'6' -> choice
67+
[ do string ":::"
68+
d <- decimal
69+
x <- takeTillEnd
70+
return $ MsgACK (ID d) (Data x)
71+
, do string ":::"
72+
d <- decimal
73+
return $ MsgACK (ID d) NoData
74+
]
75+
'7' -> string ":" >> MsgError <$> endpointParser <*> dataParser
76+
'8' -> return MsgNoop
77+
_ -> return MsgNoop
78+
79+
idParser :: Parser ID
80+
idParser = choice
81+
[ string ":" >> decimal >>= plus >>= return . IDPlus
82+
, string ":" >> decimal >>= return . ID
83+
, string ":" >> return NoID
84+
]
85+
where plus n = string "+" >> return n
12486

125-
--slash :: Parser Char
126-
--slash = char '/'
87+
endpointParser :: Parser Endpoint
88+
endpointParser = do
89+
string ":"
90+
option NoEndpoint (takeWhile1 (/= 58) >>= return . Endpoint)
12791

128-
----------------------------------------------------------------------------------
129-
---- | Non-empty text
130-
--text :: Parser String
131-
--text = many1 anyChar
92+
dataParser :: Parser Data
93+
dataParser = do
94+
string ":"
95+
option NoData (takeWhile1 (/= 58) >>= return . Data)
13296

133-
a :: ByteString
134-
a = ":{\"name\":\"hey\",\"args\":[\"haha\"]}"
13597
eventParser :: Parser Event
13698
eventParser = do
13799
string ":"
138-
t <- takeTill (== 32)
100+
t <- takeTillEnd
139101
case decode (serialize t) of
140102
Just e -> return e
141103
Nothing -> return NoEvent
142104

143-
144-
test p = parseOnly p
145-
146105
------------------------------------------------------------------------------
147106
-- | Parse given HTTP request
148107
parsePath :: ByteString -> Path
149108
parsePath p = case parseOnly pathParser p of
150109
Left _ -> WithoutSession "" ""
151110
Right x -> x
152111

153-
------------------------------------------------------------------------------
154-
-- | "/:namespace/:protocol/[:transport/:sessionID]" -> Path
155112
pathParser :: Parser Path
156113
pathParser = do
157114
string "/"

0 commit comments

Comments
 (0)