summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam T <pxqr.sta@gmail.com>2013-08-26 03:27:42 +0400
committerSam T <pxqr.sta@gmail.com>2013-08-26 03:27:42 +0400
commit8f275335d35dc56de90874825d9205e2c84dbd07 (patch)
tree3826055c2269c9dfe1550d4b210fabf85d52ab6f /src
parentdf5f9f41ed7d29be6c008198aba85d132c1339c6 (diff)
+ Add generics support.
Diffstat (limited to 'src')
-rw-r--r--src/Data/BEncode.hs140
1 files changed, 134 insertions, 6 deletions
diff --git a/src/Data/BEncode.hs b/src/Data/BEncode.hs
index 22adbb4..aab814a 100644
--- a/src/Data/BEncode.hs
+++ b/src/Data/BEncode.hs
@@ -47,6 +47,20 @@
47-- 47--
48{-# LANGUAGE FlexibleInstances #-} 48{-# LANGUAGE FlexibleInstances #-}
49{-# LANGUAGE Trustworthy #-} 49{-# LANGUAGE Trustworthy #-}
50{-# LANGUAGE CPP #-}
51
52#if __GLASGOW_HASKELL__ >= 702
53{-# LANGUAGE TypeOperators #-}
54{-# LANGUAGE DefaultSignatures #-}
55{-# LANGUAGE FlexibleContexts #-}
56{-# LANGUAGE FlexibleInstances #-}
57
58-- TODO use TF
59{-# LANGUAGE MultiParamTypeClasses #-}
60{-# LANGUAGE FunctionalDependencies #-}
61{-# LANGUAGE UndecidableInstances #-}
62#endif
63
50module Data.BEncode 64module Data.BEncode
51 ( -- * Datatype 65 ( -- * Datatype
52 BEncode(..) 66 BEncode(..)
@@ -93,11 +107,12 @@ module Data.BEncode
93import Control.Applicative 107import Control.Applicative
94import Control.Monad 108import Control.Monad
95import Data.Int 109import Data.Int
96import Data.Maybe (mapMaybe) 110import Data.List as L
97import Data.Monoid ((<>)) 111import Data.Maybe (mapMaybe)
98import Data.Foldable (foldMap) 112import Data.Monoid -- (mempty, (<>))
99import Data.Traversable (traverse) 113import Data.Foldable (foldMap)
100import Data.Word (Word8, Word16, Word32, Word64, Word) 114import Data.Traversable (traverse)
115import Data.Word (Word8, Word16, Word32, Word64, Word)
101import Data.Map (Map) 116import Data.Map (Map)
102import qualified Data.Map as M 117import qualified Data.Map as M
103import Data.Set (Set) 118import Data.Set (Set)
@@ -117,7 +132,9 @@ import Data.Version
117import Text.PrettyPrint hiding ((<>)) 132import Text.PrettyPrint hiding ((<>))
118import qualified Text.ParserCombinators.ReadP as ReadP 133import qualified Text.ParserCombinators.ReadP as ReadP
119 134
120 135#if __GLASGOW_HASKELL__ >= 702
136import GHC.Generics
137#endif
121 138
122type Dict = Map ByteString BEncode 139type Dict = Map ByteString BEncode
123 140
@@ -137,13 +154,124 @@ type Result = Either String
137 154
138class BEncodable a where 155class BEncodable a where
139 toBEncode :: a -> BEncode 156 toBEncode :: a -> BEncode
157
158#if __GLASGOW_HASKELL__ >= 702
159 default toBEncode
160 :: Generic a
161 => GBEncodable (Rep a) BEncode
162 => a -> BEncode
163
164 toBEncode = gto . from
165#endif
166
140 fromBEncode :: BEncode -> Result a 167 fromBEncode :: BEncode -> Result a
141 168
169#if __GLASGOW_HASKELL__ >= 702
170 default fromBEncode :: GBEncodable (Rep a) BEncode => BEncode -> Result a
171 fromBEncode = error "default fromBEncode: not implemented"
172#endif
142 173
143decodingError :: String -> Result a 174decodingError :: String -> Result a
144decodingError s = Left ("fromBEncode: unable to decode " ++ s) 175decodingError s = Left ("fromBEncode: unable to decode " ++ s)
145{-# INLINE decodingError #-} 176{-# INLINE decodingError #-}
146 177
178{--------------------------------------------------------------------
179 Generics
180--------------------------------------------------------------------}
181
182{- NOTE: SELECTORS FOLDING/UNFOLDING
183Both List and Map are monoids:
184
185* if fields are named, we fold record to the map;
186* otherwise we collect fields using list;
187
188and then unify them using BDict and BList constrs.
189-}
190
191#if __GLASGOW_HASKELL__ >= 702
192
193class GBEncodable f e where
194 gto :: f a -> e
195 gfrom :: e -> Result (f a)
196
197instance BEncodable f
198 => GBEncodable (K1 R f) BEncode where
199 {-# INLINE gto #-}
200 gto (K1 x) = toBEncode x
201
202 {-# INLINE gfrom #-}
203 gfrom = undefined
204
205instance Monoid e
206 => GBEncodable U1 e where
207 {-# INLINE gto #-}
208 gto U1 = mempty
209
210 {-# INLINE gfrom #-}
211 gfrom = undefined
212
213instance (GBEncodable a e, GBEncodable b e, Monoid e)
214 => GBEncodable (a :*: b) e where
215 {-# INLINE gto #-}
216 gto (a :*: b) = gto a <> gto b
217
218 {-# INLINE gfrom #-}
219 gfrom = undefined
220
221instance (GBEncodable a e, GBEncodable b e)
222 => GBEncodable (a :+: b) e where
223 {-# INLINE gto #-}
224 gto (L1 x) = gto x
225 gto (R1 x) = gto x
226
227 {-# INLINE gfrom #-}
228 gfrom = undefined
229
230instance (Selector s, GBEncodable f BEncode)
231 => GBEncodable (M1 S s f) Dict where
232 {-# INLINE gto #-}
233 gto s @ (M1 x)
234 | True || L.null sel = BC.pack sel `M.singleton` gto x
235-- | otherwise = undefined
236 where
237 sel = selName s
238
239 {-# INLINE gfrom #-}
240 gfrom = undefined
241
242-- TODO DList
243instance GBEncodable f BEncode
244 => GBEncodable (M1 S s f) [BEncode] where
245 {-# INLINE gto #-}
246 gto (M1 x) = [gto x]
247
248 gfrom = undefined
249 {-# INLINE gfrom #-}
250
251instance (Constructor c, GBEncodable f Dict, GBEncodable f [BEncode])
252 => GBEncodable (M1 C c f) BEncode where
253 {-# INLINE gto #-}
254 gto con @ (M1 x)
255 | conIsRecord con = BDict (gto x)
256 | otherwise = BList (gto x)
257
258 {-# INLINE gfrom #-}
259 gfrom = undefined
260
261instance GBEncodable f e
262 => GBEncodable (M1 D d f) e where
263 {-# INLINE gto #-}
264 gto (M1 x) = gto x
265
266 {-# INLINE gfrom #-}
267 gfrom = undefined
268
269#endif
270
271{--------------------------------------------------------------------
272 Basic instances
273--------------------------------------------------------------------}
274
147instance BEncodable BEncode where 275instance BEncodable BEncode where
148 {-# SPECIALIZE instance BEncodable BEncode #-} 276 {-# SPECIALIZE instance BEncodable BEncode #-}
149 toBEncode = id 277 toBEncode = id