{-# LANGUAGE LambdaCase  #-}
{-# LANGUAGE StrictData  #-}
{-# LANGUAGE Trustworthy #-}
module Network.Tox.Encoding where

import           Data.Binary            (Binary, get, put)
import           Data.Binary.Bits.Get   (BitGet)
import           Data.Binary.Bits.Put   (BitPut)
import           Data.Binary.Get        (Decoder (..), pushChunk,
                                         runGetIncremental)
import           Data.Binary.Put        (runPut)
import           Data.ByteString        (ByteString)
import qualified Data.ByteString        as ByteString
import qualified Data.ByteString.Lazy   as LazyByteString
import           Network.Tox.Crypto.Box (PlainText (..))


class BitEncoding a where
  bitGet :: BitGet a
  bitPut :: a -> BitPut ()


encode :: Binary a => a -> ByteString
encode :: a -> ByteString
encode =
  ByteString -> ByteString
LazyByteString.toStrict (ByteString -> ByteString) -> (a -> ByteString) -> a -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Put -> ByteString
runPut (Put -> ByteString) -> (a -> Put) -> a -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Put
forall t. Binary t => t -> Put
put


decode :: (MonadFail m, Binary a) => ByteString -> m a
decode :: ByteString -> m a
decode ByteString
bytes =
  Decoder a -> m a
forall a. Decoder a -> m a
finish (Decoder a -> m a) -> Decoder a -> m a
forall a b. (a -> b) -> a -> b
$ Decoder a -> ByteString -> Decoder a
forall a. Decoder a -> ByteString -> Decoder a
pushChunk (Get a -> Decoder a
forall a. Get a -> Decoder a
runGetIncremental Get a
forall t. Binary t => Get t
get) ByteString
bytes
  where
    finish :: Decoder a -> m a
finish = \case
      Done ByteString
unconsumed ByteOffset
_ a
output ->
        if ByteString -> Bool
ByteString.null ByteString
unconsumed
          then a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
output
          else String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> m a) -> String -> m a
forall a b. (a -> b) -> a -> b
$ String
"unconsumed input: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ PlainText -> String
forall a. Show a => a -> String
show (ByteString -> PlainText
PlainText ByteString
unconsumed)
      Fail ByteString
_ ByteOffset
_ String
msg    -> String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
msg
      Partial Maybe ByteString -> Decoder a
f       -> Decoder a -> m a
finish (Decoder a -> m a) -> Decoder a -> m a
forall a b. (a -> b) -> a -> b
$ Maybe ByteString -> Decoder a
f Maybe ByteString
forall a. Maybe a
Nothing