diff options
-rw-r--r-- | TODO.org | 2 | ||||
-rw-r--r-- | src/Data/BEncode.hs | 36 |
2 files changed, 36 insertions, 2 deletions
@@ -1,4 +1,6 @@ | |||
1 | * DONE generic decode | 1 | * DONE generic decode |
2 | * DONE tests for generics with record selectors | 2 | * DONE tests for generics with record selectors |
3 | * TODO lens compatible selectors renaming | ||
4 | * TODO benchmarks for generic decode | ||
3 | * TODO documentation | 5 | * TODO documentation |
4 | * TODO v0.1.1.0 (reason: Dict ty syn exposed) | 6 | * TODO v0.1.1.0 (reason: Dict ty syn exposed) |
diff --git a/src/Data/BEncode.hs b/src/Data/BEncode.hs index e270525..fee2774 100644 --- a/src/Data/BEncode.hs +++ b/src/Data/BEncode.hs | |||
@@ -65,11 +65,11 @@ module Data.BEncode | |||
65 | 65 | ||
66 | -- * Construction && Destructuring | 66 | -- * Construction && Destructuring |
67 | , BEncodable (..) | 67 | , BEncodable (..) |
68 | , dictAssoc | ||
69 | , Result | 68 | , Result |
70 | 69 | ||
71 | -- ** Dictionaries | 70 | -- ** Dictionaries |
72 | -- *** Building | 71 | -- *** Building |
72 | , Assoc | ||
73 | , (-->) | 73 | , (-->) |
74 | , (-->?) | 74 | , (-->?) |
75 | , fromAssocs | 75 | , fromAssocs |
@@ -146,6 +146,7 @@ data BEncode = BInteger {-# UNPACK #-} !Int64 | |||
146 | | BDict Dict | 146 | | BDict Dict |
147 | deriving (Show, Read, Eq, Ord) | 147 | deriving (Show, Read, Eq, Ord) |
148 | 148 | ||
149 | -- | Result used in decoding operations. | ||
149 | type Result = Either String | 150 | type Result = Either String |
150 | 151 | ||
151 | class BEncodable a where | 152 | class BEncodable a where |
@@ -463,13 +464,43 @@ dictAssoc = BDict . M.fromList | |||
463 | Building dictionaries | 464 | Building dictionaries |
464 | --------------------------------------------------------------------} | 465 | --------------------------------------------------------------------} |
465 | 466 | ||
467 | -- TODO Assoc = Maybe (ByteString, BEncode) | ||
468 | |||
469 | -- | /Assoc/ used to easily build dictionaries with required and | ||
470 | -- optional keys. Suppose we have we following datatype we want to | ||
471 | -- serialize: | ||
472 | -- | ||
473 | -- > data FileInfo = FileInfo | ||
474 | -- > { fileLength :: Integer | ||
475 | -- > , fileMD5sum :: Maybe ByteString | ||
476 | -- > , filePath :: [ByteString] | ||
477 | -- > , fileTags :: Maybe [Text] | ||
478 | -- > } deriving (Show, Read, Eq) | ||
479 | -- | ||
480 | -- We need to make /instance BEncodable FileInfo/, though we don't | ||
481 | -- want to check the both /maybes/ manually. The more declarative and | ||
482 | -- convenient way to define the 'toBEncode' method is to use | ||
483 | -- dictionary builders: | ||
484 | -- | ||
485 | -- > instance BEncodable FileInfo where | ||
486 | -- > toBEncode FileInfo {..} = fromAssocs | ||
487 | -- > [ "length" --> fileLength | ||
488 | -- > , "md5sum" -->? fileMD5sum | ||
489 | -- > , "path" --> filePath | ||
490 | -- > , "tags" -->? fileTags | ||
491 | -- > ] | ||
492 | -- | ||
466 | data Assoc = Required ByteString BEncode | 493 | data Assoc = Required ByteString BEncode |
467 | | Optional ByteString (Maybe BEncode) | 494 | | Optional ByteString (Maybe BEncode) |
468 | 495 | ||
496 | -- | Make required key value pair. | ||
469 | (-->) :: BEncodable a => ByteString -> a -> Assoc | 497 | (-->) :: BEncodable a => ByteString -> a -> Assoc |
470 | key --> val = Required key (toBEncode val) | 498 | key --> val = Required key (toBEncode val) |
471 | {-# INLINE (-->) #-} | 499 | {-# INLINE (-->) #-} |
472 | 500 | ||
501 | -- | Like (-->) but if the value is not present then the key do not | ||
502 | -- appear in resulting bencoded dictionary. | ||
503 | -- | ||
473 | (-->?) :: BEncodable a => ByteString -> Maybe a -> Assoc | 504 | (-->?) :: BEncodable a => ByteString -> Maybe a -> Assoc |
474 | key -->? mval = Optional key (toBEncode <$> mval) | 505 | key -->? mval = Optional key (toBEncode <$> mval) |
475 | {-# INLINE (-->?) #-} | 506 | {-# INLINE (-->?) #-} |
@@ -481,12 +512,13 @@ mkAssocs = mapMaybe unpackAssoc | |||
481 | unpackAssoc (Optional n (Just v)) = Just (n, v) | 512 | unpackAssoc (Optional n (Just v)) = Just (n, v) |
482 | unpackAssoc (Optional _ Nothing) = Nothing | 513 | unpackAssoc (Optional _ Nothing) = Nothing |
483 | 514 | ||
515 | -- | Build BEncode dictionary using key -> value description. | ||
484 | fromAssocs :: [Assoc] -> BEncode | 516 | fromAssocs :: [Assoc] -> BEncode |
485 | fromAssocs = BDict . M.fromList . mkAssocs | 517 | fromAssocs = BDict . M.fromList . mkAssocs |
486 | {-# INLINE fromAssocs #-} | 518 | {-# INLINE fromAssocs #-} |
487 | 519 | ||
488 | -- | A faster version of 'fromAssocs'. Should be used only when keys | 520 | -- | A faster version of 'fromAssocs'. Should be used only when keys |
489 | -- are sorted by ascending. | 521 | -- in builder list are sorted by ascending. |
490 | fromAscAssocs :: [Assoc] -> BEncode | 522 | fromAscAssocs :: [Assoc] -> BEncode |
491 | fromAscAssocs = BDict . M.fromList . mkAssocs | 523 | fromAscAssocs = BDict . M.fromList . mkAssocs |
492 | {-# INLINE fromAscAssocs #-} | 524 | {-# INLINE fromAscAssocs #-} |