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

import Control.Monad ((>=>))
import Data.Word
import PlutusCore.Flat.Bits (Bits, asBytes, bits, paddedBits, takeBits, toBools)
import PlutusCore.Flat.Class (Flat (..))
import PlutusCore.Flat.Encoder.Prim (eFillerF)
import PlutusCore.Flat.Encoder.Strict (Encoding (Encoding), numEncodedBits, strictEncoder)
import PlutusCore.Flat.Run (flat, unflat)
import PlutusCore.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 = (ByteString -> Decoded a
forall a b. (Flat a, AsByteString b) => b -> Decoded a
unflat (a -> ByteString
forall a. Flat a => a -> ByteString
flat a
v) Decoded a -> Decoded a -> Bool
forall a. Eq a => a -> a -> Bool
== a -> Decoded a
forall a b. b -> Either a b
Right a
v Bool -> Bool -> Bool
&& a -> NumBits -> NumBits
forall a. Flat a => a -> NumBits -> NumBits
size a
v NumBits
0 NumBits -> NumBits -> Bool
forall a. Ord a => a -> a -> Bool
>= [Bool] -> NumBits
forall a. [a] -> NumBits
forall (t :: * -> *) a. Foldable t => t a -> NumBits
length (Bits -> [Bool]
toBools (a -> Bits
forall a. Flat a => a -> Bits
bits a
v)), a -> NumBits -> NumBits
forall a. Flat a => a -> NumBits -> NumBits
size a
v NumBits
0, a -> [Word8]
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 = (ByteString -> Decoded a
forall a b. (Flat a, AsByteString b) => b -> Decoded a
unflat (a -> ByteString
forall a. Flat a => a -> ByteString
flat a
v) Decoded a -> Decoded a -> Bool
forall a. Eq a => a -> a -> Bool
== a -> Decoded a
forall a b. b -> Either a b
Right a
v, a -> NumBits -> NumBits
forall a. Flat a => a -> NumBits -> NumBits
size a
v NumBits
0, a -> String
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 = a1 -> (Bool, NumBits, [Word8])
forall a. (Eq a, Flat a) => a -> (Bool, NumBits, [Word8])
tst (a2 -> a1
f a2
l) (Bool, NumBits, [Word8]) -> (Bool, NumBits, [Word8]) -> Bool
forall a. Eq a => a -> a -> Bool
== a2 -> (Bool, NumBits, [Word8])
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 = Bits -> String
forall a. Pretty a => a -> String
prettyShow (Bits -> String) -> (a -> Bits) -> a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bits
forall a. Flat a => a -> Bits
bits

allBits :: Flat a => a -> String
allBits :: forall a. Flat a => a -> String
allBits = Bits -> String
forall a. Pretty a => a -> String
prettyShow (Bits -> String) -> (a -> Bits) -> a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bits
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 (Prim -> Encoding) -> Prim -> Encoding
forall a b. (a -> b) -> a -> b
$ Prim
enc Prim -> Prim -> Prim
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 (Bits -> [Word8]) -> (a -> Bits) -> a -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bits
forall a. Flat a => a -> Bits
bits