packages feed

silvi-0.0.2: src/Silvi/Record.hs

{-# LANGUAGE DataKinds         #-}
{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE GADTs             #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PolyKinds         #-}
{-# LANGUAGE RankNTypes        #-}
{-# LANGUAGE TypeFamilies      #-}
{-# LANGUAGE TypeInType        #-}
{-# LANGUAGE TypeOperators     #-}

module Silvi.Record
  ( rmap
  , rtraverse
  , NcsaLog
  , TestLog
  , Field(..)
  , Value(..)
  , SingField(..)
  ) where

import           Chronos.Types (OffsetDatetime (..))
import           Data.Exists   (Exists (..), Reify (..), ShowForall (..), Sing)
import           Data.Kind     (Type)
import           Data.Text     (Text)
import           GHC.Generics  (Generic)
import           Net.Types     (IPv4)
import           Silvi.Types
import           Topaz.Rec     (Rec (..), traverse)
import qualified Topaz.Rec     as Topaz

-- | Different types present in logs.
data Field
  = FieldHttpMethod          -- ^ More explicit name for Network.HTTP.Types.Method
  | FieldHttpStatus          -- ^ More explicit name for Network.HTTP.Types.Status
  | FieldHttpProtocol        -- ^ The HTTP Protocol used
  | FieldHttpProtocolVersion -- ^ More explicit name for Network.HTTP.Types.Version
  | FieldUrl                 -- ^ a url, e.g. "https://hackage.haskell.org"
  | FieldUserId              -- ^ userId as Text
  | FieldObjSize             -- ^ usually requested resource size
  | FieldIp                  -- ^ FieldIp present in log
  | FieldTimestamp           -- ^ Timestamp
  deriving (Bounded,Enum,Eq,Generic,Ord,Read,Show)

data Value :: Field -> Type where
  ValueHttpMethod :: HttpMethod -> Value 'FieldHttpMethod
  ValueHttpStatus :: HttpStatus -> Value 'FieldHttpStatus
  ValueHttpProtocol :: HttpProtocol -> Value 'FieldHttpProtocol
  ValueHttpProtocolVersion :: HttpProtocolVersion -> Value 'FieldHttpProtocolVersion
  ValueUrl :: Text -> Value 'FieldUrl
  ValueUserId :: Text -> Value 'FieldUserId
  ValueObjSize :: Int -> Value 'FieldObjSize
  ValueIp :: IPv4 -> Value 'FieldIp
  ValueTimestamp :: OffsetDatetime -> Value 'FieldTimestamp

instance ShowForall Value where
  showsPrecForall p (ValueHttpMethod x) = showParen (p > 10) $ showString "ValueHttpMethod" . showsPrec 11 x
  showsPrecForall p (ValueHttpStatus x) = showParen (p > 10) $ showString "ValueHttpStatus" . showsPrec 11 x
  showsPrecForall p (ValueHttpProtocol x) = showParen (p > 10) $ showString "ValueHttpProtocol" . showsPrec 11 x
  showsPrecForall p (ValueHttpProtocolVersion x) = showParen (p > 10) $ showString "ValueHttpProtocolVersion" . showsPrec 11 x
  showsPrecForall p (ValueUrl x) = showParen (p > 10) $ showString "ValueUrl" . showsPrec 11 x
  showsPrecForall p (ValueUserId x) = showParen (p > 10) $ showString "ValueUserId" . showsPrec 11 x
  showsPrecForall p (ValueObjSize x) = showParen (p > 10) $ showString "ValueObjSize" . showsPrec 11 x
  showsPrecForall p (ValueIp x) = showParen (p > 10) $ showString "ValueIp" . showsPrec 11 x
  showsPrecForall p (ValueTimestamp x) = showParen (p > 10) $ showString "ValueTimestamp" . showsPrec 11 x

data SingField :: Field -> Type where
  SingHttpMethod          :: SingField 'FieldHttpMethod
  SingHttpStatus          :: SingField 'FieldHttpStatus
  SingHttpProtocol        :: SingField 'FieldHttpProtocol
  SingHttpProtocolVersion :: SingField 'FieldHttpProtocolVersion
  SingUrl                 :: SingField 'FieldUrl
  SingUserId              :: SingField 'FieldUserId
  SingObjSize             :: SingField 'FieldObjSize
  SingIp                  :: SingField 'FieldIp
  SingTimestamp           :: SingField 'FieldTimestamp


type TestLog = '[ FieldIp
                , FieldTimestamp
                ]
-- | A single log entry from NCSA Common or Extended-formatted log. See:
--   http://publib.boulder.ibm.com/tividd/td/ITWSA/ITWSA_info45/en_US/HTML/guide/c-logs.html#combined
type NcsaLog = '[ FieldIp
                , FieldUserId
                , FieldTimestamp
                , FieldHttpMethod
                , FieldUrl
                , FieldHttpProtocol
                , FieldHttpProtocolVersion
                , FieldHttpStatus
                , FieldObjSize
                ]

type instance Sing = SingField
instance Reify 'FieldHttpMethod where
  reify = SingHttpMethod
instance Reify 'FieldHttpStatus where
  reify = SingHttpStatus
instance Reify 'FieldHttpProtocol where
  reify = SingHttpProtocol
instance Reify 'FieldHttpProtocolVersion where
  reify = SingHttpProtocolVersion
instance Reify 'FieldUrl where
  reify = SingUrl
instance Reify 'FieldUserId where
  reify = SingUserId
instance Reify 'FieldObjSize where
  reify = SingObjSize
instance Reify 'FieldIp where
  reify = SingIp
instance Reify 'FieldTimestamp where
  reify = SingTimestamp

-- | Alias for `Topaz.map`.
rmap :: (forall x. f x -> g x) -> Rec f as -> Rec g as
rmap = Topaz.map

-- | Alias for `Topaz.traverse`
rtraverse
  :: Applicative h
  => (forall x. f x -> h (g x))
  -> Rec f rs
  -> h (Rec g rs)
rtraverse = Topaz.traverse