<commit_before>{-|

This module provide the core classes and the associated types on which
the raaz library is crucially dependent on. These classes play a
crucial role in improving the type safety of the library and in some
cases avoids a lot of boilerplate code. Developers might need to have a
rough idea of these However, it would of very
little interest for users of the library.

-}

{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE DeriveDataTypeable         #-}
{-# LANGUAGE DefaultSignatures          #-}
{-# LANGUAGE CPP                        #-}

#include "MachDeps.h"

module Raaz.Core.Classes
       (
         -- * Type safety.
         -- $typesafety$
         -- ** Endian safe loading and storing.
         -- $endianSafe$
         EndianStore(..), toByteString
         -- ** Type safe lengths
         -- $length$
       , BYTES(..), BITS(..)
       , LengthUnit(..), inBits, atLeast, atMost
       , bitsQuotRem, bytesQuotRem
       , bitsQuot, bytesQuot
         -- ** Timing safe comparisons
         -- $timingsafe$
       , EqWord(..), (===)
       -- * Misc type and type classes.
       , HasName(..)
       , CryptoCoerce(..)
         -- ** Pointers and alignment.
       , cryptoAlignment, CryptoAlign, CryptoPtr
       , ForeignCryptoPtr
       ) where

import Data.Bits
import Data.Word
import Data.ByteString          (ByteString)
import Data.ByteString.Internal (unsafeCreate)
import Data.Typeable            (Typeable, typeOf)
import Foreign.Ptr
import Foreign.Storable
import Foreign.ForeignPtr.Safe  (ForeignPtr)

import Test.QuickCheck          (Arbitrary)

-- $typesafety$
--
-- One of the aims of raaz is to avoid many bugs by making use of the
-- type system of Haskell whenever possible. The types provided here
-- avoids two kinds of errors
--
-- 1. Endian mismatch errors.
--
-- 2. Length conversion errors.
--
-- 3. Ways to write timing safe equality checks.


-- $endianSafe$
--
-- One of the most common source of implementation problems in crypto
-- algorithms is the correct dealing of endianness. Endianness matters
-- only when we first load the data from the buffer or when we finally
-- write the data out. For types that are meant to be serialised, the
-- EndianStore instance in defined in such a way that the `load` and
-- `store` takes care of endian coversion automatically.

class Storable w => EndianStore w where

  -- | Store the given value at the locating pointed by the pointer
  store :: CryptoPtr   -- ^ the location.
        -> w           -- ^ value to store
        -> IO ()

  -- | Load the value from the location pointed by the pointer.
  load  :: CryptoPtr -> IO w

-- | Generate a bytestring representation of the object.
toByteString :: EndianStore w => w -> ByteString
toByteString w = unsafeCreate (sizeOf w) putit
      where putit ptr = store (castPtr ptr) w


-- $timingsafe$
--<commit_msg>some documentation fixes.<commit_after>{-|

This module provide the core classes and the associated types on which
the raaz library is crucially dependent on. These classes play a
crucial role in improving the type safety of the library and in some
cases avoids a lot of boilerplate code. Developers might need to have a
rough idea of these However, it would of very
little interest for users of the library.

-}

{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE DeriveDataTypeable         #-}
{-# LANGUAGE DefaultSignatures          #-}
{-# LANGUAGE CPP                        #-}

#include "MachDeps.h"

module Raaz.Core.Classes
       (
         -- * Type safety.
         -- $typesafety$


         -- ** Endian safe loading and storing.
         -- $endianSafe$
         EndianStore(..), toByteString

         -- ** Type safe lengths
         -- $length$
       , BYTES(..), BITS(..)
       , LengthUnit(..), inBits, atLeast, atMost
       , bitsQuotRem, bytesQuotRem
       , bitsQuot, bytesQuot
         -- ** Timing safe comparisons
         -- $timingsafe$
       , EqWord(..), (===)
       -- * Misc type and type classes.
       , HasName(..)
       , CryptoCoerce(..)
         -- ** Pointers and alignment.
       , cryptoAlignment, CryptoAlign, CryptoPtr
       , ForeignCryptoPtr
       ) where

import Data.Bits
import Data.Word
import Data.ByteString          (ByteString)
import Data.ByteString.Internal (unsafeCreate)
import Data.Typeable            (Typeable, typeOf)
import Foreign.Ptr
import Foreign.Storable
import Foreign.ForeignPtr.Safe  (ForeignPtr)

import Test.QuickCheck          (Arbitrary)

-- $typesafety$
--
-- One of the aims of raaz is to avoid many bugs by making use of the
-- type system of Haskell whenever possible. The types provided here
-- avoids two kinds of errors
--
-- 1. Endian mismatch errors.
--
-- 2. Length conversion errors.
--
-- 3. Ways to write timing safe equality checks.



-- $endianSafe$
--
-- One of the most common source of implementation problems in
-- crypto algorithms is the correct dealing of endianness. Endianness
-- matters only when we first load the data from the buffer or when we
-- finally write the data out. For types that are meant to be
-- serialised, the EndianStore instance in defined in such a way that
-- the `load` and `store` takes care of endian conversion
-- automatically.
class Storable w => EndianStore w where

  -- | Store the given value at the locating pointed by the pointer
  store :: CryptoPtr   -- ^ the location.
        -> w           -- ^ value to store
        -> IO ()

  -- | Load the value from the location pointed by the pointer.
  load  :: CryptoPtr -> IO w

-- | Generate a bytestring representation of the object.
toByteString :: EndianStore w => w -> ByteString
toByteString w = unsafeCreate (sizeOf w) putit
      where putit ptr = store (castPtr ptr) w


-- $timingsafe$
--
{'fraction_non_alphanumeric': 0.09426987060998152, 'fraction_numerical': 0.001008233910267182, 'mean_word_length': 2.4011428571428572, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '946551', 'n_tokens_mistral': 1722, 'n_tokens_neox': 1658, 'n_words': 666}