-- | doctest utilities
module Flat.Instances.Test (
    tst,
    tstBits,
    asList,
    flatBits,
    allBits,
    encBits,
    prettyShow,
    module Data.Word,
) where

import           Control.Monad                  ((>=>))
import           Data.Word
import           Flat.Bits                      (Bits, asBytes, bits,
                                                 paddedBits, takeBits,toBools)
import           Flat.Class                     (Flat (..))
import           Flat.Encoder.Prim              (eFillerF)
import           Flat.Encoder.Strict            (Encoding (Encoding),
                                                 numEncodedBits, strictEncoder)
import           Flat.Run                       (flat, unflat)
import           Flat.Types                     (NumBits)
import           Text.PrettyPrint.HughesPJClass (prettyShow)

-- | Returns: result of flat/unflat test, encoding size in bits, byte encoding
tst :: (Eq a, Flat a) => a -> (Bool, NumBits, [Word8])
tst :: forall a. (Eq a, Flat a) => a -> (Bool, NumBits, [Word8])
tst a
v = (forall a b. (Flat a, AsByteString b) => b -> Decoded a
unflat (forall a. Flat a => a -> ByteString
flat a
v) forall a. Eq a => a -> a -> Bool
== forall a b. b -> Either a b
Right a
v Bool -> Bool -> Bool
&& forall a. Flat a => a -> NumBits -> NumBits
size a
v NumBits
0 forall a. Ord a => a -> a -> Bool
>= forall (t :: * -> *) a. Foldable t => t a -> NumBits
length (Bits -> [Bool]
toBools (forall a. Flat a => a -> Bits
bits a
v)), forall a. Flat a => a -> NumBits -> NumBits
size a
v NumBits
0, forall a. Flat a => a -> [Word8]
showBytes a
v)

-- | Returns: result of flat/unflat test, encoding size in bits, bits encoding
tstBits :: (Eq a, Flat a) => a -> (Bool, NumBits, String)
tstBits :: forall a. (Eq a, Flat a) => a -> (Bool, NumBits, String)
tstBits a
v = (forall a b. (Flat a, AsByteString b) => b -> Decoded a
unflat (forall a. Flat a => a -> ByteString
flat a
v) forall a. Eq a => a -> a -> Bool
== forall a b. b -> Either a b
Right a
v, forall a. Flat a => a -> NumBits -> NumBits
Flat.Class.size a
v NumBits
0, forall a. Flat a => a -> String
flatBits a
v)

-- | Test that container is serialised as a List
asList :: (Eq a1, Eq a2, Flat a1, Flat a2) => (a2 -> a1) -> a2 -> Bool
asList :: forall a1 a2.
(Eq a1, Eq a2, Flat a1, Flat a2) =>
(a2 -> a1) -> a2 -> Bool
asList a2 -> a1
f a2
l = forall a. (Eq a, Flat a) => a -> (Bool, NumBits, [Word8])
tst (a2 -> a1
f a2
l) forall a. Eq a => a -> a -> Bool
== forall a. (Eq a, Flat a) => a -> (Bool, NumBits, [Word8])
tst a2
l

flatBits :: Flat a => a -> String
flatBits :: forall a. Flat a => a -> String
flatBits = forall a. Pretty a => a -> String
prettyShow forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Flat a => a -> Bits
bits

allBits :: Flat a => a -> String
allBits :: forall a. Flat a => a -> String
allBits = forall a. Pretty a => a -> String
prettyShow forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Flat a => a -> Bits
paddedBits

-- |@since 0.5
encBits :: NumBits -> Encoding -> Bits
encBits :: NumBits -> Encoding -> Bits
encBits NumBits
maxNumBits e :: Encoding
e@(Encoding Prim
enc) = NumBits -> ByteString -> Bits
takeBits (NumBits -> Encoding -> NumBits
numEncodedBits NumBits
maxNumBits Encoding
e) (NumBits -> Encoding -> ByteString
strictEncoder NumBits
maxNumBits (Prim -> Encoding
Encoding forall a b. (a -> b) -> a -> b
$ Prim
enc forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Prim
eFillerF))

showBytes :: Flat a => a -> [Word8]
showBytes :: forall a. Flat a => a -> [Word8]
showBytes = Bits -> [Word8]
asBytes forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Flat a => a -> Bits
bits