    {-# LANGUAGE OverloadedStrings #-}
    -- |
    -- Module      : Data.PEM.Writer
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : portable
    --
    module Data.PEM.Writer
        ( pemWriteLBS
        , pemWriteBS
        ) where

    import Data.PEM.Types
    import Data.ByteString (ByteString)
    import qualified Data.ByteString as B
    import qualified Data.ByteString.Char8 as BC
    import qualified Data.ByteString.Lazy as L
    import           Data.ByteArray.Encoding (Base(Base64), convertToBase)

    -- | write a PEM structure to a builder
    pemWrite :: PEM -> L.ByteString
    pemWrite :: PEM -> ByteString
    pemWrite pem :: PEM
    pem = [ByteString] -> ByteString
    L.fromChunks ([ByteString] -> ByteString) -> [ByteString] -> ByteString
    forall a b. (a -> b) -> a -> b
    $ ([ByteString
    begin,ByteString
    header][ByteString] -> [ByteString] -> [ByteString]
    forall a. [a] -> [a] -> [a]
    ++[ByteString]
    section[ByteString] -> [ByteString] -> [ByteString]
    forall a. [a] -> [a] -> [a]
    ++[ByteString
    end])
        where begin :: ByteString
    begin   = [ByteString] -> ByteString
    B.concat ["-----BEGIN ", ByteString
    sectionName, "-----\n"]
              end :: ByteString
    end     = [ByteString] -> ByteString
    B.concat ["-----END ", ByteString
    sectionName, "-----\n" ]
              section :: [ByteString]
              section :: [ByteString]
    section = (ByteString -> ByteString) -> [ByteString] -> [ByteString]
    forall a b. (a -> b) -> [a] -> [b]
    map ByteString -> ByteString
    forall bin. ByteArrayAccess bin => bin -> ByteString
    encodeLine ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
    forall a b. (a -> b) -> a -> b
    $ ByteString -> [ByteString]
    splitChunks (ByteString -> [ByteString]) -> ByteString -> [ByteString]
    forall a b. (a -> b) -> a -> b
    $ PEM -> ByteString
    pemContent PEM
    pem
              header :: ByteString
              header :: ByteString
    header  = if [(String, ByteString)] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null ([(String, ByteString)] -> Bool) -> [(String, ByteString)] -> Bool
    forall a b. (a -> b) -> a -> b
    $ PEM -> [(String, ByteString)]
    pemHeader PEM
    pem
                            then ByteString
    B.empty
                            else [ByteString] -> ByteString
    B.concat ((((String, ByteString) -> [ByteString])
    -> [(String, ByteString)] -> [ByteString]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (String, ByteString) -> [ByteString]
    toHeader (PEM -> [(String, ByteString)]
    pemHeader PEM
    pem)) [ByteString] -> [ByteString] -> [ByteString]
    forall a. [a] -> [a] -> [a]
    ++ ["\n"])
              toHeader :: (String, ByteString) -> [ByteString]
              toHeader :: (String, ByteString) -> [ByteString]
    toHeader (k :: String
    k,v :: ByteString
    v) = [ String -> ByteString
    BC.pack String
    k, ":", ByteString
    v, "\n" ]
              -- expect only ASCII. need to find a type to represent it.
              sectionName :: ByteString
    sectionName = String -> ByteString
    BC.pack (String -> ByteString) -> String -> ByteString
    forall a b. (a -> b) -> a -> b
    $ PEM -> String
    pemName PEM
    pem
              encodeLine :: bin -> ByteString
    encodeLine l :: bin
    l = Base -> bin -> ByteString
    forall bin bout.
    (ByteArrayAccess bin, ByteArray bout) =>
    Base -> bin -> bout
    convertToBase Base
    Base64 bin
    l ByteString -> ByteString -> ByteString
    `B.append` "\n"

              splitChunks :: ByteString -> [ByteString]
    splitChunks b :: ByteString
    b
                      | ByteString -> Int
    B.length ByteString
    b Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > 48 = let (x :: ByteString
    x,y :: ByteString
    y) = Int -> ByteString -> (ByteString, ByteString)
    B.splitAt 48 ByteString
    b in ByteString
    x ByteString -> [ByteString] -> [ByteString]
    forall a. a -> [a] -> [a]
    : ByteString -> [ByteString]
    splitChunks ByteString
    y
                      | Bool
    otherwise       = [ByteString
    b]

    -- | convert a PEM structure to a bytestring
    pemWriteBS :: PEM -> ByteString
    pemWriteBS :: PEM -> ByteString
    pemWriteBS = [ByteString] -> ByteString
    B.concat ([ByteString] -> ByteString)
    -> (PEM -> [ByteString]) -> PEM -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> [ByteString]
    L.toChunks (ByteString -> [ByteString])
    -> (PEM -> ByteString) -> PEM -> [ByteString]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PEM -> ByteString
    pemWrite

    -- | convert a PEM structure to a lazy bytestring
    pemWriteLBS :: PEM -> L.ByteString
    pemWriteLBS :: PEM -> ByteString
    pemWriteLBS = PEM -> ByteString
    pemWrite