diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Remote/KRPC.hs | 48 | ||||
-rw-r--r-- | src/Remote/KRPC/Method.hs | 30 |
2 files changed, 25 insertions, 53 deletions
diff --git a/src/Remote/KRPC.hs b/src/Remote/KRPC.hs index a542f0b4..5c1aadd6 100644 --- a/src/Remote/KRPC.hs +++ b/src/Remote/KRPC.hs | |||
@@ -21,6 +21,7 @@ module Remote.KRPC | |||
21 | , (==>), server | 21 | , (==>), server |
22 | ) where | 22 | ) where |
23 | 23 | ||
24 | import Control.Applicative | ||
24 | import Control.Exception | 25 | import Control.Exception |
25 | import Control.Monad.Trans.Control | 26 | import Control.Monad.Trans.Control |
26 | import Control.Monad.IO.Class | 27 | import Control.Monad.IO.Class |
@@ -39,31 +40,39 @@ data RPCException = RPCException KError | |||
39 | deriving (Show, Eq, Typeable) | 40 | deriving (Show, Eq, Typeable) |
40 | 41 | ||
41 | instance Exception RPCException | 42 | instance Exception RPCException |
43 | type RemoteAddr = KRemoteAddr | ||
42 | 44 | ||
45 | extractArgs :: BEncodable arg | ||
46 | => [ParamName] -> Map ParamName BEncode -> Result arg | ||
47 | extractArgs as d = fromBEncode =<< | ||
48 | case as of | ||
49 | [] -> Right (BList []) | ||
50 | [x] -> f x | ||
51 | xs -> BList <$> mapM f xs | ||
52 | where | ||
53 | f x = maybe (Left ("not found key " ++ BC.unpack x)) Right | ||
54 | (M.lookup x d) | ||
55 | {-# INLINE extractArgs #-} | ||
43 | 56 | ||
44 | type RemoteAddr = KRemoteAddr | 57 | injectVals :: BEncodable arg => [ParamName] -> arg -> [(ParamName, BEncode)] |
58 | injectVals [] (toBEncode -> BList []) = [] | ||
59 | injectVals [p] (toBEncode -> arg) = [(p, arg)] | ||
60 | injectVals ps (toBEncode -> BList as) = L.zip ps as | ||
61 | injectVals _ _ = error "KRPC.injectVals: impossible" | ||
62 | {-# INLINE injectVals #-} | ||
45 | 63 | ||
46 | 64 | ||
47 | queryCall :: BEncodable param | 65 | queryCall :: BEncodable param |
48 | => Extractable param | ||
49 | => KRemote -> KRemoteAddr | 66 | => KRemote -> KRemoteAddr |
50 | -> Method param result -> param -> IO () | 67 | -> Method param result -> param -> IO () |
51 | queryCall sock addr m arg = sendMessage q addr sock | 68 | queryCall sock addr m arg = sendMessage q addr sock |
52 | where | 69 | where |
53 | q = kquery (methodName m) (mkVals (methodParams m) (injector arg)) | 70 | q = kquery (methodName m) (injectVals (methodParams m) arg) |
54 | mkVals = L.zip | ||
55 | 71 | ||
56 | 72 | ||
57 | extractArgs :: [ParamName] -> Map ParamName BEncode -> Result [BEncode] | ||
58 | extractArgs as d = mapM f as | ||
59 | where | ||
60 | f x | Just y <- M.lookup x d = return y | ||
61 | | otherwise = Left ("not found key " ++ BC.unpack x) | ||
62 | {-# INLINE extractArgs #-} | ||
63 | 73 | ||
64 | -- TODO check scheme | 74 | -- TODO check scheme |
65 | getResult :: BEncodable result | 75 | getResult :: BEncodable result |
66 | => Extractable result | ||
67 | => KRemote -> KRemoteAddr | 76 | => KRemote -> KRemoteAddr |
68 | -> Method param result -> IO result | 77 | -> Method param result -> IO result |
69 | getResult sock addr m = do | 78 | getResult sock addr m = do |
@@ -71,7 +80,7 @@ getResult sock addr m = do | |||
71 | case resp of | 80 | case resp of |
72 | Left e -> throw (RPCException e) | 81 | Left e -> throw (RPCException e) |
73 | Right (respVals -> dict) -> do | 82 | Right (respVals -> dict) -> do |
74 | case extractArgs (methodVals m) dict >>= extractor of | 83 | case extractArgs (methodVals m) dict of |
75 | Right vals -> return vals | 84 | Right vals -> return vals |
76 | Left e -> throw (RPCException (ProtocolError (BC.pack e))) | 85 | Left e -> throw (RPCException (ProtocolError (BC.pack e))) |
77 | 86 | ||
@@ -81,7 +90,6 @@ getResult sock addr m = do | |||
81 | -- | 90 | -- |
82 | call :: (MonadBaseControl IO host, MonadIO host) | 91 | call :: (MonadBaseControl IO host, MonadIO host) |
83 | => (BEncodable param, BEncodable result) | 92 | => (BEncodable param, BEncodable result) |
84 | => (Extractable param, Extractable result) | ||
85 | => RemoteAddr | 93 | => RemoteAddr |
86 | -> Method param result | 94 | -> Method param result |
87 | -> param | 95 | -> param |
@@ -96,7 +104,6 @@ newtype Async result = Async { waitResult :: IO result } | |||
96 | -- TODO document errorneous usage | 104 | -- TODO document errorneous usage |
97 | async :: MonadIO host | 105 | async :: MonadIO host |
98 | => (BEncodable param, BEncodable result) | 106 | => (BEncodable param, BEncodable result) |
99 | => (Extractable param, Extractable result) | ||
100 | => RemoteAddr | 107 | => RemoteAddr |
101 | -> Method param result | 108 | -> Method param result |
102 | -> param | 109 | -> param |
@@ -119,8 +126,7 @@ type MethodHandler remote = (MethodName, HandlerBody remote) | |||
119 | 126 | ||
120 | -- we can safely erase types in (==>) | 127 | -- we can safely erase types in (==>) |
121 | (==>) :: forall (remote :: * -> *) (param :: *) (result :: *). | 128 | (==>) :: forall (remote :: * -> *) (param :: *) (result :: *). |
122 | -- (BEncodable param, BEncodable result) | 129 | (BEncodable param, BEncodable result) |
123 | (Extractable param, Extractable result) | ||
124 | => Monad remote | 130 | => Monad remote |
125 | => Method param result | 131 | => Method param result |
126 | -> (param -> remote result) | 132 | -> (param -> remote result) |
@@ -130,14 +136,13 @@ m ==> body = (methodName m, newbody) | |||
130 | where | 136 | where |
131 | {-# INLINE newbody #-} | 137 | {-# INLINE newbody #-} |
132 | newbody q = | 138 | newbody q = |
133 | case extractArgs (methodParams m) (queryArgs q) >>= extractor of | 139 | case extractArgs (methodParams m) (queryArgs q) of |
134 | Left e -> return (Left (ProtocolError (BC.pack e))) | 140 | Left e -> return (Left (ProtocolError (BC.pack e))) |
135 | Right a -> do | 141 | Right a -> do |
136 | r <- body a | 142 | r <- body a |
137 | return (Right (kresponse (mkVals (methodVals m) (injector r)))) | 143 | return (Right (kresponse (injectVals (methodVals m) r))) |
138 | 144 | ||
139 | mkVals :: [ValName] -> [BEncode] -> [(ValName, BEncode)] | 145 | infix 1 ==> |
140 | mkVals = L.zip | ||
141 | 146 | ||
142 | -- TODO: allow forkIO | 147 | -- TODO: allow forkIO |
143 | server :: (MonadBaseControl IO remote, MonadIO remote) | 148 | server :: (MonadBaseControl IO remote, MonadIO remote) |
@@ -153,6 +158,3 @@ server servport handlers = do | |||
153 | handlerMap = M.fromList handlers | 158 | handlerMap = M.fromList handlers |
154 | dispatch s = M.lookup s handlerMap | 159 | dispatch s = M.lookup s handlerMap |
155 | invoke m q = m q | 160 | invoke m q = m q |
156 | |||
157 | bimap f _ (Left x) = Left (f x) | ||
158 | 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 d0c8e89a..4283256b 100644 --- a/src/Remote/KRPC/Method.hs +++ b/src/Remote/KRPC/Method.hs | |||
@@ -16,9 +16,6 @@ module Remote.KRPC.Method | |||
16 | 16 | ||
17 | -- * Predefined methods | 17 | -- * Predefined methods |
18 | , idM | 18 | , idM |
19 | |||
20 | -- * Internal | ||
21 | , Extractable(..) | ||
22 | ) where | 19 | ) where |
23 | 20 | ||
24 | import Control.Applicative | 21 | import Control.Applicative |
@@ -69,30 +66,3 @@ idM = method "id" ["x"] ["y"] | |||
69 | method :: MethodName -> [ParamName] -> [ValName] -> Method param result | 66 | method :: MethodName -> [ParamName] -> [ValName] -> Method param result |
70 | method = Method | 67 | method = Method |
71 | {-# INLINE method #-} | 68 | {-# INLINE method #-} |
72 | |||
73 | |||
74 | |||
75 | class Extractable a where | ||
76 | injector :: a -> [BEncode] | ||
77 | extractor :: [BEncode] -> Result a | ||
78 | |||
79 | instance (BEncodable a, BEncodable b) => Extractable (a, b) where | ||
80 | {- SPECIALIZE instance (BEncodable a, BEncodable b) => Extractable (a, b) -} | ||
81 | injector (a, b) = [toBEncode a, toBEncode b] | ||
82 | {-# INLINE injector #-} | ||
83 | |||
84 | extractor [a, b] = (,) <$> fromBEncode a <*> fromBEncode b | ||
85 | extractor _ = decodingError "unable to match pair" | ||
86 | {-# INLINE extractor #-} | ||
87 | |||
88 | {- | ||
89 | instance BEncodable a => Extractable a where | ||
90 | {-# SPECIALIZE instance BEncodable a => Extractable a #-} | ||
91 | |||
92 | injector x = [toBEncode x] | ||
93 | {-# INLINE injector #-} | ||
94 | |||
95 | extractor [x] = fromBEncode x | ||
96 | extractor _ = decodingError "unable to match single value" | ||
97 | {-# INLINE extractor #-} | ||
98 | -} \ No newline at end of file | ||