-- | This module exposes some core types used through out the Raaz
-- library. One of the major goals of the raaz cryptographic library
-- is to use the type safety of Haskell to catch some common
-- bugs at compile time.
--
-- __WARNING:__ If you are just a user of this library, it is unlikely
-- that you will need to import this module. It is only required if
-- you are a developer and want to define a new cryptographic data
-- type.

module Raaz.Core.Types
       ( -- * Overview.
         -- $overview$
         module Raaz.Core.Types.Equality
       , module Raaz.Core.Types.Endian
       , module Raaz.Core.Types.Pointer
       , module Raaz.Core.Types.Aligned
       , module Raaz.Core.Types.Tuple
       , module Raaz.Core.Types.Copying
       , Describable(..)
       ) where

import Raaz.Core.Types.Aligned
import Raaz.Core.Types.Describe
import Raaz.Core.Types.Equality
import Raaz.Core.Types.Endian
import Raaz.Core.Types.Pointer
import Raaz.Core.Types.Tuple
import Raaz.Core.Types.Copying( Src, Dest, source, destination)


-- $overview$
--
-- A lot of cryptographic code is low level and involves quite a bit
-- of boilerplate and are therefore fertile grounds for bugs. This
-- module describes types specific to raaz that are designed to catch
-- bugs in such low level code. The three principles that we follow
-- in the design are:
--
-- 1. Define distinct types for semantically different objects. For
--    example, distinguish between buffer length/pointer offset in
--    bytes versus other units (see `LengthUnit`) or make endian aware
--    variants of standard word types (see `BE` and `LE`) etc.
--
-- 2. Make sure that the low level functions are sensitive to these
--    types. For example, the function `sizeOf` exposed here returns
--    @`BYTES` `Int`@ instead of just `Int` and functions like
--    `allocaBuffer` are generic enough to work with any length units.
--
-- 3. Provide obvious instances for some basic type and have and
--    idiom/design pattern to build such interfaces for user defined
--    types. For example, we have a very specific way to build timing
--    safe equality functions for arbitrary types. Most of the time,
--    in our case it just amounts to handling product types.
--
-- == Role of Monoids.
--
-- Monoids play an important role in facilitating the top down
-- approach to type safety that we mentioned above. Some types
-- described here have a natural monoid semantics. For example, when
-- dealing with pointer offsets and buffer sizes, we use type safe
-- length units like `BYTES`. These length units are instances of
-- monoids where the underlying operation is addition. On the other
-- hand, when it comes to pointer alignment which is captured by the
-- type `Alignment`, the monoid operation is taking the lowest common
-- multiple.
--
{-# ANN module "HLint: ignore Use import/export shortcut" #-}
