Skip to content

Commit 6528a49

Browse files
committed
Expect json input separated by STX, fix haskell#43
1 parent 01adeab commit 6528a49

File tree

1 file changed

+20
-10
lines changed

1 file changed

+20
-10
lines changed

src/Haskell/Ide/Engine/Transport/JsonStdio.hs

+20-10
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@
44
module Haskell.Ide.Engine.Transport.JsonStdio where
55

66
import Control.Concurrent
7+
import Control.Lens (view)
78
import Control.Logging
89
import qualified Data.Aeson as A
10+
import qualified Data.ByteString.Char8 as B
11+
import qualified Data.ByteString.Lazy as BL
12+
import Data.Char
913
import qualified Data.Map as Map
14+
import qualified Data.Text as T
1015
import Haskell.Ide.Engine.PluginDescriptor
1116
import Haskell.Ide.Engine.Types
1217
import Pipes
1318
import qualified Pipes.Aeson as P
1419
import qualified Pipes.ByteString as P
15-
import qualified Pipes.Prelude as P
16-
import qualified Data.ByteString.Char8 as B
17-
import qualified Data.ByteString.Lazy as BL
18-
import qualified Data.Text as T
1920
import Pipes.Parse
21+
import qualified Pipes.Prelude as P hiding (drop,length)
2022
import System.IO
2123

2224
-- TODO: Can pass in a handle, then it is general
@@ -25,19 +27,27 @@ jsonStdioTransport cin = do
2527
cout <- newChan :: IO (Chan ChannelResponse)
2628
hSetBuffering stdout NoBuffering
2729
let
30+
processParse cid r stream = do
31+
writeChan cin (wireToChannel cout cid r)
32+
rsp <- readChan cout
33+
BL.putStr $ A.encode (channelToWire rsp)
34+
loop (cid + 1) (P.drop (1::Int) stream)
2835
loop cid stream = do
2936
debug "jsonStdioTransport:calling go"
30-
(req,stream') <- runStateT decodeMsg stream
37+
let splitStream = view (P.break (== fromIntegral (ord '\STX'))) stream
38+
(req,res) <- runStateT decodeMsg splitStream
3139
debug $ T.pack $ "jsonStdioTransport:got:" ++ show req
3240
case req of
3341
Just (Left err) -> do
3442
putStr $ show (HieError (A.String $ T.pack $ show err))
35-
loop (cid + 1) stream'
3643
Just (Right r) -> do
37-
writeChan cin (wireToChannel cout cid r)
38-
rsp <- readChan cout
39-
BL.putStr $ A.encode (channelToWire rsp)
40-
loop (cid + 1) stream'
44+
nextStreamOrError <- next res
45+
case nextStreamOrError of
46+
Left nextStream -> processParse cid r nextStream
47+
Right (a,restConsumer) -> do (restLength,nextStream) <- P.fold' (\n bs -> n + fromIntegral (B.length bs)) 0 id restConsumer
48+
if (B.length a + restLength > 0) then
49+
putStr $ show (HieError (A.String $ "Unexpected input before separator"))
50+
else processParse cid r nextStream
4151
Nothing -> do
4252
-- exit the loop
4353
putStr $ show (HieError (A.String $ T.pack $ "Got Nothing"))

0 commit comments

Comments
 (0)