    -- |
    -- Module      : Codec.Serialise.Properties
    -- Copyright   : (c) Duncan Coutts 2015-2017
    -- License     : BSD3-style (see LICENSE.txt)
    --
    -- Maintainer  : duncan@community.haskell.org
    -- Stability   : experimental
    -- Portability : non-portable (GHC extensions)
    --
    -- This module contains a set of generally useful properties, which
    -- instance authors are encouraged to use in order to test their
    -- instances of the @'Serialise'@ class. For example, if you have a
    -- data type which you might derive or write instances for:
    --
    -- @
    -- data Foo = Foo { fooInt :: Int, fooBool :: Bool }
    --   deriving (Eq, Show, 'GHC.Generics.Generic')
    -- -- or, alternatively
    -- instance 'Serialise' Foo where
    --   'encode' = ...
    --   'decode' = ...
    -- @
    --
    -- Then you can use this module to easily derive some quick
    -- properties:
    --
    -- @
    -- import qualified "Codec.Serialise.Properties" as Props
    --
    -- fooSerialiseId :: Foo -> Bool
    -- fooSerialiseId = Props.'serialiseIdentity'
    --
    -- fooFlatTermId :: Foo -> Bool
    -- fooFlatTermId = Props.'flatTermIdentity'
    --
    -- fooHasValidFlatTerm :: Foo -> Bool
    -- fooHasValidFlatTerm = Props.'hasValidFlatTerm'
    -- @
    --
    -- You can then conveniently use these three functions with
    -- QuickCheck, for example.
    --
    module Codec.Serialise.Properties
      ( -- * CBOR Properties
        serialiseIdentity -- :: (Serialise a, Eq a) => a -> Bool
        -- * @'FlatTerm'@ Properties
      , flatTermIdentity  -- :: (Serialise a, Eq a) => a -> Bool
      , hasValidFlatTerm  -- ::  Serialise a        => a -> Bool
      ) where

    import           Codec.CBOR.FlatTerm
    import           Codec.Serialise       (deserialise, serialise)
    import           Codec.Serialise.Class

    --------------------------------------------------------------------------------

    -- | Ensure that serializing and deserializing some value results in
    -- the original value being returned.
    --
    -- @since 0.2.0.0
    serialiseIdentity :: (Serialise a, Eq a) => a -> Bool
    serialiseIdentity :: forall a. (Serialise a, Eq a) => a -> Bool
    serialiseIdentity a
    a = a
    a a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == (ByteString -> a
    forall a. Serialise a => ByteString -> a
    deserialise (ByteString -> a) -> (a -> ByteString) -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> ByteString
    forall a. Serialise a => a -> ByteString
    serialise) a
    a

    -- | Ensure that serializing and deserializing a value with the
    -- @'FlatTerm'@ form results in the original value being returned.
    --
    -- @since 0.2.0.0
    flatTermIdentity :: (Serialise a, Eq a) => a -> Bool
    flatTermIdentity :: forall a. (Serialise a, Eq a) => a -> Bool
    flatTermIdentity  a
    a = a -> Either String a
    forall a b. b -> Either a b
    Right a
    a Either String a -> Either String a -> Bool
    forall a. Eq a => a -> a -> Bool
    == (FlatTerm -> Either String a
    fromFlat (FlatTerm -> Either String a)
    -> (a -> FlatTerm) -> a -> Either String a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> FlatTerm
    toFlat) a
    a
      where
        toFlat :: a -> FlatTerm
    toFlat   = Encoding -> FlatTerm
    toFlatTerm (Encoding -> FlatTerm) -> (a -> Encoding) -> a -> FlatTerm
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Encoding
    forall a. Serialise a => a -> Encoding
    encode
        fromFlat :: FlatTerm -> Either String a
    fromFlat = (forall s. Decoder s a) -> FlatTerm -> Either String a
    forall a. (forall s. Decoder s a) -> FlatTerm -> Either String a
    fromFlatTerm Decoder s a
    forall s. Decoder s a
    forall a s. Serialise a => Decoder s a
    decode

    -- | Ensure that serializing a value into a @'FlatTerm'@ gives us a
    -- valid @'FlatTerm'@ back.
    --
    -- @since 0.2.0.0
    hasValidFlatTerm :: Serialise a => a -> Bool
    hasValidFlatTerm :: forall a. Serialise a => a -> Bool
    hasValidFlatTerm = FlatTerm -> Bool
    validFlatTerm (FlatTerm -> Bool) -> (a -> FlatTerm) -> a -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Encoding -> FlatTerm
    toFlatTerm (Encoding -> FlatTerm) -> (a -> Encoding) -> a -> FlatTerm
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Encoding
    forall a. Serialise a => a -> Encoding
    encode