content: {-# LANGUAGE CPP #-}
  #ifdef SAFE_HASKELL
  {-# LANGUAGE Trustworthy #-}
  #endif
  
  -----------------------------------------------------------------------------
  -- |
  -- Module      :  Data.SafeCopy
  -- Copyright   :  PublicDomain
  --
  -- Maintainer  :  lemmih@gmail.com
  -- Portability :  non-portable (uses GHC extensions)
  --
  -- SafeCopy extends the parsing and serialization capabilities of Data.Serialize
  -- to include nested version control. Nested version control means that you
  -- can change the definition and binary format of a type nested deep within
  -- other types without problems.
  --
  -- = Migration
  --
  -- Consider this scenario. You want to store your contact list on disk
  -- and so write the following code:
  --
  -- @
  --type Name     = String
  --type Address  = String
  --data Contacts = Contacts [(Name, Address)]
  --instance SafeCopy Contacts where
  --     putCopy (Contacts list) = contain $ safePut list
  --     getCopy = contain $ Contacts \<$\> safeGet
  -- @
  --
  -- At this point, everything is fine. You get the awesome speed of Data.Serialize
  -- together with Haskell's ease of use. However, things quickly take a U-turn for the worse
  -- when you realize that you want to keep phone numbers as well as names and
  -- addresses. Being the experienced coder that you are, you see that using a 3-tuple
  -- isn't very pretty and you'd rather use a record. At first you fear that this
  -- change in structure will invalidate all your old data. Those fears are quickly quelled,
  -- though, when you remember how nifty SafeCopy is. With renewed enthusiasm,
  -- you set out and write the following code:
  --
  -- @
  --type Name = String
  --type Address = String
  --type Phone = String
  --
  --{- We rename our old Contacts structure -}
  --data Contacts_v0 = Contacts_v0 [(Name, Address)]
  --instance SafeCopy Contacts_v0 where
  --     putCopy (Contacts_v0 list) = contain $ safePut list
  --     getCopy = contain $ Contacts_v0 \<$\> safeGet
  --
  --data Contact = Contact { name    :: Name
  --                       , address :: Address
  --                       , phone   :: Phone }
  --instance SafeCopy Contact where
  --    putCopy Contact{..} = contain $ do safePut name; safePut address; safePut phone
  --    getCopy = contain $ Contact \<$\> safeGet \<*\> safeGet \<*\> safeGet
  --
  --data Contacts = Contacts [Contact]
  --instance SafeCopy Contacts where
  --     version = 2
  --     kind = extension
  --     putCopy (Contacts contacts) = contain $ safePut contacts
  --     getCopy = contain $ Contacts \<$\> safeGet
  --
  --{- Here the magic happens: -}
  --instance Migrate Contacts where
  --     type MigrateFrom Contacts = Contacts_v0
  --     migrate (Contacts_v0 contacts) = Contacts [ Contact{ name    = name
  --                                                        , address = address
  --                                                        , phone   = \"\" }
  --                                               | (name, address) <- contacts ]
  -- @
  --
  -- With this, you reflect on your code and you are happy. You feel confident in the safety of
  -- your data and you know you can remove @Contacts_v0@ once you no longer wish to support
  -- that legacy format.
  --
  -- = Retiring Migrations
  --
  -- There may come a time when you have to remove @Contacts_v0@.
  -- Perhaps it uses types you want to remove from your build to
  -- decrease its size.  Perhaps it has constraints such as @Enum@ which
  -- are imposed on your new @Contacts@ type via the @SafeCopy@
  -- instance.
  --
  -- In any case, if you are using @safecopy@ incombination with
  -- @acid-state@, some care must be taken when removing @Contacts_v0@.
  -- The following steps must be taken to add a new type and remove the old:
  --
  --   1. Add the migration as described above.
  --   2. Run the server with the new migration on /all important data/.  This
  --      will cause the type to be modified in the running program.
  --   3. /Restart/ the server with the new migration on /all important data/.  This
  --      causes checkpoints to be written that only contain the new type.
  --   4. Remove the old type from your source code, changing the @kind@ of
  --      the new type from @extension@ to @base@. Build and deploy.
  --
  -- If you omit any of these steps it is a certainty that you will
  -- proceed happily with your development thinking all is grand, and
  -- then when you go to deploy your live system the migration will fail.
  
  module Data.SafeCopy
      (
        safeGet
      , safePut
      , SafeCopy(version, kind, getCopy, putCopy, objectProfile, errorTypeName)
      , SafeCopy'
      , Profile(..)
      , Prim(..)
      , Migrate(..)
      , Reverse(..)
      , Kind
      , extension
      , extended_extension
      , extended_base
      , base
      , Contained
      , contain
      , Version
  
        -- * Template haskell functions
      , deriveSafeCopy
      , deriveSafeCopyIndexedType
      , deriveSafeCopySimple
      , deriveSafeCopySimpleIndexedType
      , deriveSafeCopyHappstackData
      , deriveSafeCopyHappstackDataIndexedType
  
        -- * Rarely used functions
      , getSafeGet
      , getSafePut
      , primitive
      ) where
  
  import Data.SafeCopy.Instances ()
  import Data.SafeCopy.SafeCopy
  import Data.SafeCopy.Derive
  