-- |
-- Module      : Data.ASN1.Pretty
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : experimental
-- Portability : unknown
--
module Data.ASN1.Pretty
    ( pretty
    , PrettyType(..)
    ) where

import           Data.ASN1.Types
import           Data.ASN1.BitArray
import           Data.ByteArray.Encoding (convertToBase, Base(..))
import           Data.ByteString (ByteString)
import           Numeric (showHex)

data PrettyType = Multiline Int -- Offset where to start
                | SingleLine
    deriving (Int -> PrettyType -> ShowS
[PrettyType] -> ShowS
PrettyType -> String
(Int -> PrettyType -> ShowS)
-> (PrettyType -> String)
-> ([PrettyType] -> ShowS)
-> Show PrettyType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PrettyType] -> ShowS
$cshowList :: [PrettyType] -> ShowS
show :: PrettyType -> String
$cshow :: PrettyType -> String
showsPrec :: Int -> PrettyType -> ShowS
$cshowsPrec :: Int -> PrettyType -> ShowS
Show,PrettyType -> PrettyType -> Bool
(PrettyType -> PrettyType -> Bool)
-> (PrettyType -> PrettyType -> Bool) -> Eq PrettyType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PrettyType -> PrettyType -> Bool
$c/= :: PrettyType -> PrettyType -> Bool
== :: PrettyType -> PrettyType -> Bool
$c== :: PrettyType -> PrettyType -> Bool
Eq)

-- | Pretty Print a list of ASN.1 element
pretty :: PrettyType -- ^ indent level in space character
       -> [ASN1]     -- ^ stream of ASN1
       -> String
pretty :: PrettyType -> [ASN1] -> String
pretty (Multiline at :: Int
at) = Int -> [ASN1] -> String
prettyPrint Int
at
  where
    indent :: Int -> String
indent n :: Int
n = Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
n ' '

    prettyPrint :: Int -> [ASN1] -> String
prettyPrint _ []                 = ""
    prettyPrint n :: Int
n (x :: ASN1
x@(Start _) : xs :: [ASN1]
xs) = Int -> String
indent Int
n     String -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS -> ASN1 -> String
forall t. (String -> t) -> ASN1 -> t
p ShowS
forall a. a -> a
id ASN1
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> [ASN1] -> String
prettyPrint (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) [ASN1]
xs
    prettyPrint n :: Int
n (x :: ASN1
x@(End _) : xs :: [ASN1]
xs)   = Int -> String
indent (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-1) String -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS -> ASN1 -> String
forall t. (String -> t) -> ASN1 -> t
p ShowS
forall a. a -> a
id ASN1
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> [ASN1] -> String
prettyPrint (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-1) [ASN1]
xs
    prettyPrint n :: Int
n (x :: ASN1
x : xs :: [ASN1]
xs)           = Int -> String
indent Int
n     String -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS -> ASN1 -> String
forall t. (String -> t) -> ASN1 -> t
p ShowS
forall a. a -> a
id ASN1
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> [ASN1] -> String
prettyPrint Int
n [ASN1]
xs

pretty SingleLine = [ASN1] -> String
prettyPrint
  where
    prettyPrint :: [ASN1] -> String
prettyPrint []                 = ""
    prettyPrint (x :: ASN1
x@(Start _) : xs :: [ASN1]
xs) = ShowS -> ASN1 -> String
forall t. (String -> t) -> ASN1 -> t
p ShowS
forall a. a -> a
id ASN1
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ "," String -> ShowS
forall a. [a] -> [a] -> [a]
++ [ASN1] -> String
prettyPrint [ASN1]
xs
    prettyPrint (x :: ASN1
x@(End _) : xs :: [ASN1]
xs)   = ShowS -> ASN1 -> String
forall t. (String -> t) -> ASN1 -> t
p ShowS
forall a. a -> a
id ASN1
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ "," String -> ShowS
forall a. [a] -> [a] -> [a]
++ [ASN1] -> String
prettyPrint [ASN1]
xs
    prettyPrint (x :: ASN1
x : xs :: [ASN1]
xs)           = ShowS -> ASN1 -> String
forall t. (String -> t) -> ASN1 -> t
p ShowS
forall a. a -> a
id ASN1
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ "," String -> ShowS
forall a. [a] -> [a] -> [a]
++ [ASN1] -> String
prettyPrint [ASN1]
xs

p :: ([Char] -> t) -> ASN1 -> t
p :: (String -> t) -> ASN1 -> t
p put :: String -> t
put (Boolean b :: Bool
b)                        = String -> t
put ("bool: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Bool -> String
forall a. Show a => a -> String
show Bool
b)
p put :: String -> t
put (IntVal i :: Integer
i)                         = String -> t
put ("int: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Integer -> ShowS
forall a. (Integral a, Show a) => a -> ShowS
showHex Integer
i "")
p put :: String -> t
put (BitString bits :: BitArray
bits)                   = String -> t
put ("bitstring: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ (ByteString -> String
hexdump (ByteString -> String) -> ByteString -> String
forall a b. (a -> b) -> a -> b
$ BitArray -> ByteString
bitArrayGetData BitArray
bits))
p put :: String -> t
put (OctetString bs :: ByteString
bs)                   = String -> t
put ("octetstring: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
hexdump ByteString
bs)
p put :: String -> t
put (ASN1
Null)                             = String -> t
put "null"
p put :: String -> t
put (OID is :: OID
is)                           = String -> t
put ("OID: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ OID -> String
forall a. Show a => a -> String
show OID
is)
p put :: String -> t
put (Real d :: Double
d)                           = String -> t
put ("real: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
d)
p put :: String -> t
put (Enumerated _)                     = String -> t
put "enum"
p put :: String -> t
put (Start Sequence)                   = String -> t
put "{"
p put :: String -> t
put (End Sequence)                     = String -> t
put "}"
p put :: String -> t
put (Start Set)                        = String -> t
put "["
p put :: String -> t
put (End Set)                          = String -> t
put "]"
p put :: String -> t
put (Start (Container x :: ASN1Class
x y :: Int
y))            = String -> t
put ("< " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ASN1Class -> String
forall a. Show a => a -> String
show ASN1Class
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ " " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
y)
p put :: String -> t
put (End (Container x :: ASN1Class
x y :: Int
y))              = String -> t
put ("> " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ASN1Class -> String
forall a. Show a => a -> String
show ASN1Class
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ " " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
y)
p put :: String -> t
put (ASN1String cs :: ASN1CharacterString
cs)                    = (String -> t) -> ASN1CharacterString -> t
forall t. (String -> t) -> ASN1CharacterString -> t
putCS String -> t
put ASN1CharacterString
cs
p put :: String -> t
put (ASN1Time TimeUTC time :: DateTime
time tz :: Maybe TimezoneOffset
tz)         = String -> t
put ("utctime: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ DateTime -> String
forall a. Show a => a -> String
show DateTime
time String -> ShowS
forall a. [a] -> [a] -> [a]
++ " " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Maybe TimezoneOffset -> String
forall a. Show a => a -> String
show Maybe TimezoneOffset
tz)
p put :: String -> t
put (ASN1Time TimeGeneralized time :: DateTime
time tz :: Maybe TimezoneOffset
tz) = String -> t
put ("generalizedtime: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ DateTime -> String
forall a. Show a => a -> String
show DateTime
time String -> ShowS
forall a. [a] -> [a] -> [a]
++ " " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Maybe TimezoneOffset -> String
forall a. Show a => a -> String
show Maybe TimezoneOffset
tz)
p put :: String -> t
put (Other tc :: ASN1Class
tc tn :: Int
tn x :: ByteString
x)                    = String -> t
put ("other(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ASN1Class -> String
forall a. Show a => a -> String
show ASN1Class
tc String -> ShowS
forall a. [a] -> [a] -> [a]
++ "," String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
tn String -> ShowS
forall a. [a] -> [a] -> [a]
++ "," String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show ByteString
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ ")")

putCS :: ([Char] -> t) -> ASN1CharacterString -> t
putCS :: (String -> t) -> ASN1CharacterString -> t
putCS put :: String -> t
put (ASN1CharacterString UTF8 t :: ByteString
t)         = String -> t
put ("utf8string:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show ByteString
t)
putCS put :: String -> t
put (ASN1CharacterString Numeric bs :: ByteString
bs)     = String -> t
put ("numericstring:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
hexdump ByteString
bs)
putCS put :: String -> t
put (ASN1CharacterString Printable t :: ByteString
t)    = String -> t
put ("printablestring: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show ByteString
t)
putCS put :: String -> t
put (ASN1CharacterString T61 bs :: ByteString
bs)         = String -> t
put ("t61string:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show ByteString
bs)
putCS put :: String -> t
put (ASN1CharacterString VideoTex bs :: ByteString
bs)    = String -> t
put ("videotexstring:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
hexdump ByteString
bs)
putCS put :: String -> t
put (ASN1CharacterString IA5 bs :: ByteString
bs)         = String -> t
put ("ia5string:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show ByteString
bs)
putCS put :: String -> t
put (ASN1CharacterString Graphic bs :: ByteString
bs)     = String -> t
put ("graphicstring:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
hexdump ByteString
bs)
putCS put :: String -> t
put (ASN1CharacterString Visible bs :: ByteString
bs)     = String -> t
put ("visiblestring:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
hexdump ByteString
bs)
putCS put :: String -> t
put (ASN1CharacterString General bs :: ByteString
bs)     = String -> t
put ("generalstring:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
hexdump ByteString
bs)
putCS put :: String -> t
put (ASN1CharacterString UTF32 t :: ByteString
t)        = String -> t
put ("universalstring:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show ByteString
t)
putCS put :: String -> t
put (ASN1CharacterString Character bs :: ByteString
bs)   = String -> t
put ("characterstring:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
hexdump ByteString
bs)
putCS put :: String -> t
put (ASN1CharacterString BMP t :: ByteString
t)          = String -> t
put ("bmpstring: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show ByteString
t)

hexdump :: ByteString -> String
hexdump :: ByteString -> String
hexdump bs :: ByteString
bs = ByteString -> String
forall a. Show a => a -> String
show (Base -> ByteString -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> bout
convertToBase Base
Base16 ByteString
bs :: ByteString)