diff options
author | Sam T <pxqr.sta@gmail.com> | 2013-05-12 01:07:34 +0400 |
---|---|---|
committer | Sam T <pxqr.sta@gmail.com> | 2013-05-12 01:07:34 +0400 |
commit | fd62eb70fe87b471d29cb994a60ad88f58b33ca9 (patch) | |
tree | ed8c7d69f10c1b874cc03c7d6e5064fb81b94482 /src/Remote | |
parent | 7614ed760e137219fb4e36288abf1e78eacb2266 (diff) |
~ Prepare to scheme check.
Diffstat (limited to 'src/Remote')
-rw-r--r-- | src/Remote/KRPC.hs | 54 | ||||
-rw-r--r-- | src/Remote/KRPC/Method.hs | 22 | ||||
-rw-r--r-- | src/Remote/KRPC/Protocol.hs | 17 |
3 files changed, 64 insertions, 29 deletions
diff --git a/src/Remote/KRPC.hs b/src/Remote/KRPC.hs index 8f2027f2..22dbf3aa 100644 --- a/src/Remote/KRPC.hs +++ b/src/Remote/KRPC.hs | |||
@@ -10,6 +10,7 @@ | |||
10 | {-# LANGUAGE OverloadedStrings #-} | 10 | {-# LANGUAGE OverloadedStrings #-} |
11 | {-# LANGUAGE FlexibleContexts, DeriveDataTypeable #-} | 11 | {-# LANGUAGE FlexibleContexts, DeriveDataTypeable #-} |
12 | {-# LANGUAGE ExplicitForAll, KindSignatures #-} | 12 | {-# LANGUAGE ExplicitForAll, KindSignatures #-} |
13 | {-# LANGUAGE ViewPatterns #-} | ||
13 | module Remote.KRPC | 14 | module Remote.KRPC |
14 | ( module Remote.KRPC.Method, RemoteAddr | 15 | ( module Remote.KRPC.Method, RemoteAddr |
15 | 16 | ||
@@ -17,7 +18,7 @@ module Remote.KRPC | |||
17 | , call, async, await | 18 | , call, async, await |
18 | 19 | ||
19 | -- * Server | 20 | -- * Server |
20 | , server | 21 | , (==>), server |
21 | ) where | 22 | ) where |
22 | 23 | ||
23 | import Control.Exception | 24 | import Control.Exception |
@@ -27,6 +28,7 @@ import Control.Monad.IO.Class | |||
27 | import Data.BEncode | 28 | import Data.BEncode |
28 | import Data.List as L | 29 | import Data.List as L |
29 | import Data.Map as M | 30 | import Data.Map as M |
31 | import Data.Set as S | ||
30 | import Data.Text as T | 32 | import Data.Text as T |
31 | import Data.Typeable | 33 | import Data.Typeable |
32 | import Network | 34 | import Network |
@@ -51,6 +53,7 @@ queryCall sock addr m arg = sendMessage q addr sock | |||
51 | where | 53 | where |
52 | q = kquery (L.head (methodName m)) [(L.head (methodParams m), toBEncode arg)] | 54 | q = kquery (L.head (methodName m)) [(L.head (methodParams m), toBEncode arg)] |
53 | 55 | ||
56 | -- TODO check scheme | ||
54 | getResult :: BEncodable result | 57 | getResult :: BEncodable result |
55 | => KRemote -> KRemoteAddr | 58 | => KRemote -> KRemoteAddr |
56 | -> Method param result -> IO result | 59 | -> Method param result -> IO result |
@@ -58,7 +61,7 @@ getResult sock addr m = do | |||
58 | resp <- recvResponse addr sock | 61 | resp <- recvResponse addr sock |
59 | case resp of | 62 | case resp of |
60 | Left e -> throw (RPCException e) | 63 | Left e -> throw (RPCException e) |
61 | Right (KResponse dict) -> do | 64 | Right (respVals -> dict) -> do |
62 | let valName = L.head (methodVals m) | 65 | let valName = L.head (methodVals m) |
63 | case M.lookup valName dict of | 66 | case M.lookup valName dict of |
64 | Just val | Right res <- fromBEncode val -> return res | 67 | Just val | Right res <- fromBEncode val -> return res |
@@ -102,10 +105,10 @@ async addr m arg = do | |||
102 | await :: MonadIO host => Async result -> host result | 105 | await :: MonadIO host => Async result -> host result |
103 | await = liftIO . waitResult | 106 | await = liftIO . waitResult |
104 | 107 | ||
105 | -- TODO better name | 108 | type HandlerBody remote = (BEncode -> remote (Result BEncode), KResponseScheme) |
106 | type MHandler remote = ( Method BEncode (Result BEncode) | 109 | |
107 | , BEncode -> remote (Result BEncode) | 110 | type MethodHandler remote = (KQueryScheme, HandlerBody remote) |
108 | ) | 111 | |
109 | 112 | ||
110 | -- we can safely erase types in (==>) | 113 | -- we can safely erase types in (==>) |
111 | (==>) :: forall (remote :: * -> *) (param :: *) (result :: *). | 114 | (==>) :: forall (remote :: * -> *) (param :: *) (result :: *). |
@@ -113,8 +116,8 @@ type MHandler remote = ( Method BEncode (Result BEncode) | |||
113 | => Monad remote | 116 | => Monad remote |
114 | => Method param result | 117 | => Method param result |
115 | -> (param -> remote result) | 118 | -> (param -> remote result) |
116 | -> MHandler remote | 119 | -> MethodHandler remote |
117 | m ==> body = undefined | 120 | m ==> body = (methodQueryScheme m, (newbody, methodRespScheme m)) |
118 | where | 121 | where |
119 | newbody x = case fromBEncode x of | 122 | newbody x = case fromBEncode x of |
120 | Right a -> liftM (Right . toBEncode) (body a) | 123 | Right a -> liftM (Right . toBEncode) (body a) |
@@ -125,15 +128,28 @@ m ==> body = undefined | |||
125 | -- TODO: allow overloading | 128 | -- TODO: allow overloading |
126 | server :: (MonadBaseControl IO remote, MonadIO remote) | 129 | server :: (MonadBaseControl IO remote, MonadIO remote) |
127 | => PortNumber | 130 | => PortNumber |
128 | -> [MHandler remote] | 131 | -> [MethodHandler remote] |
129 | -> remote () | 132 | -> remote () |
130 | server servport ms = remoteServer servport $ \_ q -> do | 133 | server servport handlers = do |
131 | let name = queryMethod q | 134 | remoteServer servport $ \_ q -> do |
132 | let args = undefined -- queryArgs q | 135 | case dispatch (scheme q) of |
133 | let m = L.head ms | 136 | Nothing -> return (Left (MethodUnknown "method")) |
134 | res <- undefined -- methodBody m (snd (L.head (M.toList args))) | 137 | Just (m, rsc) -> do |
135 | case res of | 138 | let arg = snd (L.head (M.toList (queryArgs q))) |
136 | Left r -> return (Left (ProtocolError (T.pack r))) | 139 | |
137 | Right r -> do | 140 | res <- invoke m arg |
138 | let retName = undefined -- L.head (methodVals m) | 141 | let valName = L.head (S.toList (rscVals rsc)) |
139 | return (Right (kresponse [(retName, r)])) | 142 | return $ bimap (ProtocolError . T.pack) |
143 | (kresponse . return . (,) valName) res | ||
144 | where | ||
145 | handlerMap = M.fromList handlers | ||
146 | |||
147 | -- dispatch :: KQueryScheme -> MethodHandler remote | ||
148 | dispatch s | Just m <- M.lookup s handlerMap = return m | ||
149 | | otherwise = Nothing | ||
150 | |||
151 | -- invoke :: MethodHandler remote -> BEncode -> remote BEncode | ||
152 | invoke m args = m args | ||
153 | |||
154 | bimap f _ (Left x) = Left (f x) | ||
155 | bimap _ g (Right x) = Right (g x) \ No newline at end of file | ||
diff --git a/src/Remote/KRPC/Method.hs b/src/Remote/KRPC/Method.hs index 3c757d07..420ceacf 100644 --- a/src/Remote/KRPC/Method.hs +++ b/src/Remote/KRPC/Method.hs | |||
@@ -1,6 +1,14 @@ | |||
1 | -- | | ||
2 | -- Copyright : (c) Sam T. 2013 | ||
3 | -- License : MIT | ||
4 | -- Maintainer : pxqr.sta@gmail.com | ||
5 | -- Stability : experimental | ||
6 | -- Portability : portable | ||
7 | -- | ||
1 | {-# LANGUAGE OverloadedStrings #-} | 8 | {-# LANGUAGE OverloadedStrings #-} |
2 | module Remote.KRPC.Method | 9 | module Remote.KRPC.Method |
3 | ( Method(methodName, methodParams, methodVals) | 10 | ( Method(methodName, methodParams, methodVals) |
11 | , methodQueryScheme, methodRespScheme | ||
4 | 12 | ||
5 | -- * Construction | 13 | -- * Construction |
6 | , method | 14 | , method |
@@ -10,13 +18,16 @@ module Remote.KRPC.Method | |||
10 | ) where | 18 | ) where |
11 | 19 | ||
12 | import Prelude hiding ((.), id) | 20 | import Prelude hiding ((.), id) |
21 | import Control.Applicative | ||
13 | import Control.Category | 22 | import Control.Category |
14 | import Control.Monad | 23 | import Control.Monad |
24 | import Data.ByteString as B | ||
25 | import Data.List as L | ||
26 | import Data.Set as S | ||
15 | 27 | ||
16 | import Remote.KRPC.Protocol | 28 | import Remote.KRPC.Protocol |
17 | 29 | ||
18 | 30 | ||
19 | |||
20 | -- | The | 31 | -- | The |
21 | -- | 32 | -- |
22 | -- * argument: type of method parameter | 33 | -- * argument: type of method parameter |
@@ -44,6 +55,15 @@ instance Category Method where | |||
44 | (.) = composeM | 55 | (.) = composeM |
45 | {-# INLINE (.) #-} | 56 | {-# INLINE (.) #-} |
46 | 57 | ||
58 | methodQueryScheme :: Method a b -> KQueryScheme | ||
59 | methodQueryScheme = KQueryScheme <$> B.intercalate "." . methodName | ||
60 | <*> S.fromList . methodParams | ||
61 | {-# INLINE methodQueryScheme #-} | ||
62 | |||
63 | |||
64 | methodRespScheme :: Method a b -> KResponseScheme | ||
65 | methodRespScheme = KResponseScheme . S.fromList . methodVals | ||
66 | {-# INLINE methodRespScheme #-} | ||
47 | 67 | ||
48 | -- TODO ppMethod | 68 | -- TODO ppMethod |
49 | 69 | ||
diff --git a/src/Remote/KRPC/Protocol.hs b/src/Remote/KRPC/Protocol.hs index e7fbea11..625aba25 100644 --- a/src/Remote/KRPC/Protocol.hs +++ b/src/Remote/KRPC/Protocol.hs | |||
@@ -24,12 +24,12 @@ module Remote.KRPC.Protocol | |||
24 | , KError(..), errorCode, mkKError | 24 | , KError(..), errorCode, mkKError |
25 | 25 | ||
26 | -- * Query | 26 | -- * Query |
27 | , KQuery(queryMethod, queryParams), MethodName, ParamName, kquery | 27 | , KQuery(queryMethod, queryArgs), MethodName, ParamName, kquery |
28 | , KQueryScheme(qscMethod, qscParams) | 28 | , KQueryScheme(KQueryScheme, qscMethod, qscParams) |
29 | 29 | ||
30 | -- * Response | 30 | -- * Response |
31 | , KResponse(respVals), ValName, kresponse | 31 | , KResponse(respVals), ValName, kresponse |
32 | , KResponseScheme(rscVals) | 32 | , KResponseScheme(KResponseScheme, rscVals) |
33 | 33 | ||
34 | , sendMessage, recvResponse | 34 | , sendMessage, recvResponse |
35 | 35 | ||
@@ -46,12 +46,14 @@ import Control.Exception.Lifted | |||
46 | import Control.Monad | 46 | import Control.Monad |
47 | import Control.Monad.IO.Class | 47 | import Control.Monad.IO.Class |
48 | import Control.Monad.Trans.Control | 48 | import Control.Monad.Trans.Control |
49 | |||
49 | import Data.BEncode | 50 | import Data.BEncode |
50 | import Data.ByteString as B | 51 | import Data.ByteString as B |
51 | import qualified Data.ByteString.Lazy as LB | 52 | import qualified Data.ByteString.Lazy as LB |
52 | import Data.Map as M | 53 | import Data.Map as M |
53 | import Data.Set as S | 54 | import Data.Set as S |
54 | import Data.Text as T | 55 | import Data.Text as T |
56 | |||
55 | import Network.Socket hiding (recvFrom) | 57 | import Network.Socket hiding (recvFrom) |
56 | import Network.Socket.ByteString | 58 | import Network.Socket.ByteString |
57 | 59 | ||
@@ -134,7 +136,7 @@ type ParamName = ByteString | |||
134 | -- TODO document that it is and how transferred | 136 | -- TODO document that it is and how transferred |
135 | data KQuery = KQuery { | 137 | data KQuery = KQuery { |
136 | queryMethod :: MethodName | 138 | queryMethod :: MethodName |
137 | , queryParams :: Map ParamName BEncode | 139 | , queryArgs :: Map ParamName BEncode |
138 | } deriving (Show, Read, Eq, Ord) | 140 | } deriving (Show, Read, Eq, Ord) |
139 | 141 | ||
140 | instance BEncodable KQuery where | 142 | instance BEncodable KQuery where |
@@ -160,12 +162,9 @@ data KQueryScheme = KQueryScheme { | |||
160 | , qscParams :: Set ParamName | 162 | , qscParams :: Set ParamName |
161 | } deriving (Show, Read, Eq, Ord) | 163 | } deriving (Show, Read, Eq, Ord) |
162 | 164 | ||
163 | domen :: Map a b -> Set a | ||
164 | domen = error "scheme.domen" | ||
165 | |||
166 | instance KMessage KQuery KQueryScheme where | 165 | instance KMessage KQuery KQueryScheme where |
167 | {-# SPECIALIZE instance KMessage KQuery KQueryScheme #-} | 166 | {-# SPECIALIZE instance KMessage KQuery KQueryScheme #-} |
168 | scheme q = KQueryScheme (queryMethod q) (domen (queryParams q)) | 167 | scheme q = KQueryScheme (queryMethod q) (M.keysSet (queryArgs q)) |
169 | {-# INLINE scheme #-} | 168 | {-# INLINE scheme #-} |
170 | 169 | ||
171 | type ValName = ByteString | 170 | type ValName = ByteString |
@@ -198,7 +197,7 @@ newtype KResponseScheme = KResponseScheme { | |||
198 | 197 | ||
199 | instance KMessage KResponse KResponseScheme where | 198 | instance KMessage KResponse KResponseScheme where |
200 | {-# SPECIALIZE instance KMessage KResponse KResponseScheme #-} | 199 | {-# SPECIALIZE instance KMessage KResponse KResponseScheme #-} |
201 | scheme = KResponseScheme . domen . respVals | 200 | scheme = KResponseScheme . keysSet . respVals |
202 | {-# INLINE scheme #-} | 201 | {-# INLINE scheme #-} |
203 | 202 | ||
204 | 203 | ||