{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Data.Bencode.Encode
(
Encoding
, toBuilder
, string
, text
, integer
, int
, int64
, int32
, int16
, int8
, word
, word64
, word32
, word16
, word8
, list
, dict
, field
, dict'
, FieldEncodings
, value
) where
import Data.Int
import Data.Monoid (Endo(..))
import Data.Word
import qualified Data.ByteString as B
import qualified Data.ByteString.Builder as BB
import qualified Data.Map as M
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Vector as V
import Data.Bencode.Type (Value(..))
newtype Encoding = Encoding { Encoding -> Builder
unEncoding :: BB.Builder }
toBuilder :: Encoding -> BB.Builder
toBuilder :: Encoding -> Builder
toBuilder = Encoding -> Builder
unEncoding
string :: B.ByteString -> Encoding
string :: ByteString -> Encoding
string ByteString
s = Builder -> Encoding
Encoding forall a b. (a -> b) -> a -> b
$ Int -> Builder
BB.intDec (ByteString -> Int
B.length ByteString
s) forall a. Semigroup a => a -> a -> a
<> Char -> Builder
BB.char7 Char
':' forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
BB.byteString ByteString
s
integer :: Integer -> Encoding
integer :: Integer -> Encoding
integer = forall a. (a -> Builder) -> a -> Encoding
integer_ Integer -> Builder
BB.integerDec
list :: (a -> Encoding) -> V.Vector a -> Encoding
list :: forall a. (a -> Encoding) -> Vector a -> Encoding
list a -> Encoding
enc Vector a
vs =
Builder -> Encoding
Encoding forall a b. (a -> b) -> a -> b
$ Char -> Builder
BB.char7 Char
'l' forall a. Semigroup a => a -> a -> a
<> forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (Encoding -> Builder
unEncoding forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Encoding
enc) Vector a
vs forall a. Semigroup a => a -> a -> a
<> Char -> Builder
BB.char7 Char
'e'
{-# INLINE list #-}
dict :: (a -> Encoding) -> M.Map B.ByteString a -> Encoding
dict :: forall a. (a -> Encoding) -> Map ByteString a -> Encoding
dict a -> Encoding
enc Map ByteString a
kvs = Builder -> Encoding
Encoding forall a b. (a -> b) -> a -> b
$ Char -> Builder
BB.char7 Char
'd' forall a. Semigroup a => a -> a -> a
<> Map ByteString a -> Builder
f Map ByteString a
kvs forall a. Semigroup a => a -> a -> a
<> Char -> Builder
BB.char7 Char
'e'
where
f :: Map ByteString a -> Builder
f = forall m k a. Monoid m => (k -> a -> m) -> Map k a -> m
M.foldMapWithKey (\ByteString
k a
v -> Encoding -> Builder
unEncoding (ByteString -> Encoding
string ByteString
k) forall a. Semigroup a => a -> a -> a
<> Encoding -> Builder
unEncoding (a -> Encoding
enc a
v))
{-# INLINE dict #-}
text :: T.Text -> Encoding
text :: Text -> Encoding
text = ByteString -> Encoding
string forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
T.encodeUtf8
{-# INLINE text #-}
int :: Int -> Encoding
int :: Int -> Encoding
int = forall a. (a -> Builder) -> a -> Encoding
integer_ Int -> Builder
BB.intDec
word :: Word -> Encoding
word :: Word -> Encoding
word = forall a. (a -> Builder) -> a -> Encoding
integer_ Word -> Builder
BB.wordDec
field :: B.ByteString -> (a -> Encoding) -> a -> FieldEncodings
field :: forall a. ByteString -> (a -> Encoding) -> a -> FieldEncodings
field ByteString
k a -> Encoding
enc a
v = Endo [(ByteString, Encoding)] -> FieldEncodings
FE (forall a. (a -> a) -> Endo a
Endo ((ByteString
k, a -> Encoding
enc a
v)forall a. a -> [a] -> [a]
:))
{-# INLINE field #-}
dict' :: FieldEncodings -> Encoding
dict' :: FieldEncodings -> Encoding
dict' = forall a. (a -> Encoding) -> Map ByteString a -> Encoding
dict forall a. a -> a
id forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Ord k => [(k, a)] -> Map k a
M.fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a b. (a -> b) -> a -> b
$ []) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Endo a -> a -> a
appEndo forall b c a. (b -> c) -> (a -> b) -> a -> c
. FieldEncodings -> Endo [(ByteString, Encoding)]
unFE
{-# INLINE dict' #-}
newtype FieldEncodings = FE { FieldEncodings -> Endo [(ByteString, Encoding)]
unFE :: Endo [(B.ByteString, Encoding)] }
deriving (NonEmpty FieldEncodings -> FieldEncodings
FieldEncodings -> FieldEncodings -> FieldEncodings
forall b. Integral b => b -> FieldEncodings -> FieldEncodings
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: forall b. Integral b => b -> FieldEncodings -> FieldEncodings
$cstimes :: forall b. Integral b => b -> FieldEncodings -> FieldEncodings
sconcat :: NonEmpty FieldEncodings -> FieldEncodings
$csconcat :: NonEmpty FieldEncodings -> FieldEncodings
<> :: FieldEncodings -> FieldEncodings -> FieldEncodings
$c<> :: FieldEncodings -> FieldEncodings -> FieldEncodings
Semigroup, Semigroup FieldEncodings
FieldEncodings
[FieldEncodings] -> FieldEncodings
FieldEncodings -> FieldEncodings -> FieldEncodings
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [FieldEncodings] -> FieldEncodings
$cmconcat :: [FieldEncodings] -> FieldEncodings
mappend :: FieldEncodings -> FieldEncodings -> FieldEncodings
$cmappend :: FieldEncodings -> FieldEncodings -> FieldEncodings
mempty :: FieldEncodings
$cmempty :: FieldEncodings
Monoid)
value :: Value -> Encoding
value :: Value -> Encoding
value Value
v = case Value
v of
String ByteString
s -> ByteString -> Encoding
string ByteString
s
Integer Integer
i -> Integer -> Encoding
integer Integer
i
List Vector Value
vs -> forall a. (a -> Encoding) -> Vector a -> Encoding
list Value -> Encoding
value Vector Value
vs
Dict Map ByteString Value
vs -> forall a. (a -> Encoding) -> Map ByteString a -> Encoding
dict Value -> Encoding
value Map ByteString Value
vs
int64 :: Int64 -> Encoding
int64 :: Int64 -> Encoding
int64 = forall a. (a -> Builder) -> a -> Encoding
integer_ Int64 -> Builder
BB.int64Dec
int32 :: Int32 -> Encoding
int32 :: Int32 -> Encoding
int32 = forall a. (a -> Builder) -> a -> Encoding
integer_ Int32 -> Builder
BB.int32Dec
int16 :: Int16 -> Encoding
int16 :: Int16 -> Encoding
int16 = forall a. (a -> Builder) -> a -> Encoding
integer_ Int16 -> Builder
BB.int16Dec
int8 :: Int8 -> Encoding
int8 :: Int8 -> Encoding
int8 = forall a. (a -> Builder) -> a -> Encoding
integer_ Int8 -> Builder
BB.int8Dec
word64 :: Word64 -> Encoding
word64 :: Word64 -> Encoding
word64 = forall a. (a -> Builder) -> a -> Encoding
integer_ Word64 -> Builder
BB.word64Dec
word32 :: Word32 -> Encoding
word32 :: Word32 -> Encoding
word32 = forall a. (a -> Builder) -> a -> Encoding
integer_ Word32 -> Builder
BB.word32Dec
word16 :: Word16 -> Encoding
word16 :: Word16 -> Encoding
word16 = forall a. (a -> Builder) -> a -> Encoding
integer_ Word16 -> Builder
BB.word16Dec
word8 :: Word8 -> Encoding
word8 :: Word8 -> Encoding
word8 = forall a. (a -> Builder) -> a -> Encoding
integer_ Word8 -> Builder
BB.word8Dec
integer_ :: (a -> BB.Builder) -> a -> Encoding
integer_ :: forall a. (a -> Builder) -> a -> Encoding
integer_ a -> Builder
f = \a
x -> Builder -> Encoding
Encoding forall a b. (a -> b) -> a -> b
$ Char -> Builder
BB.char7 Char
'i' forall a. Semigroup a => a -> a -> a
<> a -> Builder
f a
x forall a. Semigroup a => a -> a -> a
<> Char -> Builder
BB.char7 Char
'e'
{-# INLINE integer_ #-}