module Data.PEM.Parser
( pemParser
, pemParseBS
, pemParseLBS
) where
import Control.Applicative
import Data.Attoparsec
import qualified Data.Attoparsec.Lazy as AttoLazy
import Data.Attoparsec.Char8 (space)
import Data.PEM.Types
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as BC
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Base64 as Base64
import Prelude hiding (takeWhile)
import Data.Serialize.Builder
import Data.Monoid
pemParser :: Parser [PEM]
pemParser = many contextSection
where
beginMarker = string "-----BEGIN " >> return ()
endMarker = string "-----END " >> return ()
skipLine = skipWhile (/= 0xa) >> space >> return ()
eatLine = takeWhile (/= 0xa) <* space
contextSection = manyTill skipLine beginMarker *> section
section = do
name <- takeWhile (/= 0x2d) <* (string "-----" *> space)
l <- manyTill eatLine endMarker
let content = toByteString $ mconcat $ map (fromByteString . Base64.decodeLenient) l
return $ PEM { pemName = BC.unpack name, pemHeader = [], pemContent = content }
pemParseBS :: ByteString -> Either String [PEM]
pemParseBS = parseOnly pemParser
pemParseLBS :: L.ByteString -> Either String [PEM]
pemParseLBS = AttoLazy.eitherResult . AttoLazy.parse pemParser