1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
{-# LANGUAGE
ScopedTypeVariables #-}
module Main
( main
)
where
import qualified Data.ByteString as B
import qualified Data.Vector.Storable as V
import Data.Word
import System.ByteOrder -- package 'byteorder'
import Test.QuickCheck
import Foreign.Storable
import Data.Vector.Storable.ByteString
arbList :: (Bounded a, Integral a) => Gen [a]
arbList = choose (0, 16384) >>= flip vectorOf arbitraryBoundedIntegral
instance Arbitrary B.ByteString where
arbitrary = fmap B.pack arbList
instance (Bounded a, Integral a, Storable a) => Arbitrary (V.Vector a) where
arbitrary = fmap V.fromList arbList
-- Reference implementations
fromBE, fromHost :: (Integral a) => [Word8] -> a
fromBE = foldl (\n x -> n * 256 + fromIntegral x) 0
fromHost = case byteOrder of
LittleEndian -> fromBE . reverse
BigEndian -> fromBE
toLE, toHost :: (Integral a) => Int -> a -> [Word8]
toLE sz = take sz . map (fromIntegral . (`mod` 256)) . iterate (`div` 256)
toHost = case byteOrder of
LittleEndian -> toLE
BigEndian -> \sz -> reverse . toLE sz
data Rep a = Rep Int ([Word8] -> a) (a -> [Word8])
rep8 :: Rep Word8
rep8 = Rep 1 (\[x] -> x) return
repN :: forall a . (Storable a, Integral a) => Rep a
repN = let n = sizeOf (undefined :: a) in Rep n fromHost (toHost n)
ref_byteStringToVector :: (Storable a) => Rep a -> B.ByteString -> V.Vector a
ref_byteStringToVector (Rep n f _) = V.fromList . go where
go bs = case B.splitAt n bs of
(x, xs) | B.length x == n -> f (B.unpack x) : go xs
_ -> []
ref_vectorToByteString :: (Storable a) => Rep a -> V.Vector a -> B.ByteString
ref_vectorToByteString (Rep _ _ f) = B.pack . concatMap f . V.toList
-- Properties
mkProp_inv _ x = byteStringToVector (vectorToByteString x) == x
mkProp_inv_ref r x = ref_byteStringToVector r (ref_vectorToByteString r x) == x
mkProp_inv_ref1 r x = ref_byteStringToVector r (vectorToByteString x) == x
mkProp_inv_ref2 r x = byteStringToVector (ref_vectorToByteString r x) == x
mkProp_eq_BV r x = ref_byteStringToVector r x == byteStringToVector x
mkProp_eq_VB r x = ref_vectorToByteString r x == vectorToByteString x
-- Test runner
runFor :: (Integral a, Bounded a, Storable a, Show a) => Rep a -> IO ()
runFor r = do
mapM_
(quickCheck . ($ r))
[ mkProp_inv
, mkProp_inv_ref
, mkProp_inv_ref1
, mkProp_inv_ref2
, mkProp_eq_VB
]
quickCheck (mkProp_eq_BV r)
main :: IO ()
main = do
runFor rep8
runFor (repN :: Rep Word16)
runFor (repN :: Rep Word32)
runFor (repN :: Rep Word64)
|