4
4
module Haskell.Ide.Engine.Transport.JsonStdio where
5
5
6
6
import Control.Concurrent
7
+ import Control.Lens (view )
7
8
import Control.Logging
8
9
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
9
13
import qualified Data.Map as Map
14
+ import qualified Data.Text as T
10
15
import Haskell.Ide.Engine.PluginDescriptor
11
16
import Haskell.Ide.Engine.Types
12
17
import Pipes
13
18
import qualified Pipes.Aeson as P
14
19
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
19
20
import Pipes.Parse
21
+ import qualified Pipes.Prelude as P hiding (drop ,length )
20
22
import System.IO
21
23
22
24
-- TODO: Can pass in a handle, then it is general
@@ -25,19 +27,27 @@ jsonStdioTransport cin = do
25
27
cout <- newChan :: IO (Chan ChannelResponse )
26
28
hSetBuffering stdout NoBuffering
27
29
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)
28
35
loop cid stream = do
29
36
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
31
39
debug $ T. pack $ " jsonStdioTransport:got:" ++ show req
32
40
case req of
33
41
Just (Left err) -> do
34
42
putStr $ show (HieError (A. String $ T. pack $ show err))
35
- loop (cid + 1 ) stream'
36
43
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
41
51
Nothing -> do
42
52
-- exit the loop
43
53
putStr $ show (HieError (A. String $ T. pack $ " Got Nothing" ))
0 commit comments