{-# OPTIONS_GHC -fno-warn-orphans #-}

module Data.GenValidity.ByteString where

import qualified Data.ByteString as SB
import qualified Data.ByteString.Lazy as LB
import qualified Data.ByteString.Lazy.Internal as LB
import qualified Data.ByteString.Short as Short
import Data.GenValidity
import Data.Validity.ByteString ()
import Data.Word (Word8)
import System.Random as Random
import Test.QuickCheck
import Test.QuickCheck.Gen
import Test.QuickCheck.Random

-- |
--
-- > genValid = SB.pack <$> genValid
-- > shrinkValid = fmap SB.pack . shrinkValid . SB.unpack
instance GenValid SB.ByteString where
  genValid :: Gen ByteString
genValid = Gen Word8 -> Gen ByteString
genStrictByteStringBy forall a. GenValid a => Gen a
genValid
  shrinkValid :: ByteString -> [ByteString]
shrinkValid = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Word8] -> ByteString
SB.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. GenValid a => a -> [a]
shrinkValid forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [Word8]
SB.unpack

genStrictByteStringBy :: Gen Word8 -> Gen SB.ByteString
genStrictByteStringBy :: Gen Word8 -> Gen ByteString
genStrictByteStringBy (MkGen QCGen -> Int -> Word8
word8Func) = do
  Int
len <- Gen Int
genListLength
  forall a. (QCGen -> Int -> a) -> Gen a
MkGen forall a b. (a -> b) -> a -> b
$ \QCGen
qcgen Int
size ->
    let go :: QCGen -> Maybe (Word8, QCGen)
        go :: QCGen -> Maybe (Word8, QCGen)
go QCGen
qcg =
          let (QCGen
qc1, QCGen
qc2) = forall g. RandomGen g => g -> (g, g)
Random.split QCGen
qcg
           in forall a. a -> Maybe a
Just (QCGen -> Int -> Word8
word8Func QCGen
qc1 Int
size, QCGen
qc2)
     in forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall a.
Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)
SB.unfoldrN Int
len QCGen -> Maybe (Word8, QCGen)
go QCGen
qcgen

instance GenValid LB.ByteString where
  genValid :: Gen ByteString
genValid = Gen ByteString -> Gen ByteString
genLazyByteStringByStrictByteString forall a. GenValid a => Gen a
genValid
  shrinkValid :: ByteString -> [ByteString]
shrinkValid = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Word8] -> ByteString
LB.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. GenValid a => a -> [a]
shrinkValid forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [Word8]
LB.unpack

genLazyByteStringBy :: Gen Word8 -> Gen LB.ByteString
genLazyByteStringBy :: Gen Word8 -> Gen ByteString
genLazyByteStringBy Gen Word8
gen = Gen ByteString -> Gen ByteString
genLazyByteStringByStrictByteString (Gen Word8 -> Gen ByteString
genStrictByteStringBy Gen Word8
gen)

genLazyByteStringByStrictByteString :: Gen SB.ByteString -> Gen LB.ByteString
genLazyByteStringByStrictByteString :: Gen ByteString -> Gen ByteString
genLazyByteStringByStrictByteString Gen ByteString
gen =
  forall a. (Int -> Gen a) -> Gen a
sized forall a b. (a -> b) -> a -> b
$ \Int
s -> do
    [Int]
ss <- Int -> Gen [Int]
arbPartition Int
s
    [Int] -> Gen ByteString
go [Int]
ss
  where
    go :: [Int] -> Gen ByteString
go [] = forall (f :: * -> *) a. Applicative f => a -> f a
pure ByteString
LB.Empty
    go (Int
s : [Int]
ss) = ByteString -> ByteString -> ByteString
LB.Chunk forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Int -> Gen a -> Gen a
resize Int
s Gen ByteString
gen forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Int] -> Gen ByteString
go [Int]
ss

instance GenValid Short.ShortByteString where
  genValid :: Gen ShortByteString
genValid = [Word8] -> ShortByteString
Short.pack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. GenValid a => Gen a
genValid
  shrinkValid :: ShortByteString -> [ShortByteString]
shrinkValid = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Word8] -> ShortByteString
Short.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. GenValid a => a -> [a]
shrinkValid forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> [Word8]
Short.unpack