    -- |
    -- Module      : Data.X509.CertificateChain
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : unknown
    --
    module Data.X509.CertificateChain
        ( CertificateChain(..)
        , CertificateChainRaw(..)
        -- * marshall between CertificateChain and CertificateChainRaw
        , decodeCertificateChain
        , encodeCertificateChain
        ) where

    import Data.X509.Cert (Certificate)
    import Data.X509.Signed (SignedExact, decodeSignedObject, encodeSignedObject)
    import Data.ByteString (ByteString)

    -- | A chain of X.509 certificates in exact form.
    newtype CertificateChain = CertificateChain [SignedExact Certificate]
        deriving (Show,Eq)

    -- | Represent a chain of X.509 certificates in bytestring form.
    newtype CertificateChainRaw = CertificateChainRaw [ByteString]
        deriving (Show,Eq)

    -- | Decode a CertificateChainRaw into a CertificateChain if every
    -- raw certificate are decoded correctly, otherwise return the index of the
    -- failed certificate and the error associated.
    decodeCertificateChain :: CertificateChainRaw -> Either (Int, String) CertificateChain
    decodeCertificateChain (CertificateChainRaw l) =
        either Left (Right . CertificateChain) $ loop 0 l
      where loop _ []     = Right []
            loop i (r:rs) = case decodeSignedObject r of
                             Left err -> Left (i, err)
                             Right o  -> either Left (Right . (o :)) $ loop (i+1) rs

    -- | Convert a CertificateChain into a CertificateChainRaw
    encodeCertificateChain :: CertificateChain -> CertificateChainRaw
    encodeCertificateChain (CertificateChain chain) =
        CertificateChainRaw $ map encodeSignedObject chain