{-# LANGUAGE PatternSynonyms #-}

-- | Utility functions for enclosing a code segment with tracing events.
module Ouroboros.Consensus.Util.Enclose (
    Enclosing
  , Enclosing' (..)
  , encloseWith
  , pattern FallingEdge
  ) where

import           Control.Tracer (Tracer, traceWith)

data Enclosing' a =
    -- | Preceding a specific code segment.
    RisingEdge
    -- | Succeeding a specific code segment, with extra information.
  | FallingEdgeWith !a
  deriving (Int -> Enclosing' a -> ShowS
[Enclosing' a] -> ShowS
Enclosing' a -> String
(Int -> Enclosing' a -> ShowS)
-> (Enclosing' a -> String)
-> ([Enclosing' a] -> ShowS)
-> Show (Enclosing' a)
forall a. Show a => Int -> Enclosing' a -> ShowS
forall a. Show a => [Enclosing' a] -> ShowS
forall a. Show a => Enclosing' a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Enclosing' a] -> ShowS
$cshowList :: forall a. Show a => [Enclosing' a] -> ShowS
show :: Enclosing' a -> String
$cshow :: forall a. Show a => Enclosing' a -> String
showsPrec :: Int -> Enclosing' a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Enclosing' a -> ShowS
Show, Enclosing' a -> Enclosing' a -> Bool
(Enclosing' a -> Enclosing' a -> Bool)
-> (Enclosing' a -> Enclosing' a -> Bool) -> Eq (Enclosing' a)
forall a. Eq a => Enclosing' a -> Enclosing' a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Enclosing' a -> Enclosing' a -> Bool
$c/= :: forall a. Eq a => Enclosing' a -> Enclosing' a -> Bool
== :: Enclosing' a -> Enclosing' a -> Bool
$c== :: forall a. Eq a => Enclosing' a -> Enclosing' a -> Bool
Eq, Eq (Enclosing' a)
Eq (Enclosing' a)
-> (Enclosing' a -> Enclosing' a -> Ordering)
-> (Enclosing' a -> Enclosing' a -> Bool)
-> (Enclosing' a -> Enclosing' a -> Bool)
-> (Enclosing' a -> Enclosing' a -> Bool)
-> (Enclosing' a -> Enclosing' a -> Bool)
-> (Enclosing' a -> Enclosing' a -> Enclosing' a)
-> (Enclosing' a -> Enclosing' a -> Enclosing' a)
-> Ord (Enclosing' a)
Enclosing' a -> Enclosing' a -> Bool
Enclosing' a -> Enclosing' a -> Ordering
Enclosing' a -> Enclosing' a -> Enclosing' a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (Enclosing' a)
forall a. Ord a => Enclosing' a -> Enclosing' a -> Bool
forall a. Ord a => Enclosing' a -> Enclosing' a -> Ordering
forall a. Ord a => Enclosing' a -> Enclosing' a -> Enclosing' a
min :: Enclosing' a -> Enclosing' a -> Enclosing' a
$cmin :: forall a. Ord a => Enclosing' a -> Enclosing' a -> Enclosing' a
max :: Enclosing' a -> Enclosing' a -> Enclosing' a
$cmax :: forall a. Ord a => Enclosing' a -> Enclosing' a -> Enclosing' a
>= :: Enclosing' a -> Enclosing' a -> Bool
$c>= :: forall a. Ord a => Enclosing' a -> Enclosing' a -> Bool
> :: Enclosing' a -> Enclosing' a -> Bool
$c> :: forall a. Ord a => Enclosing' a -> Enclosing' a -> Bool
<= :: Enclosing' a -> Enclosing' a -> Bool
$c<= :: forall a. Ord a => Enclosing' a -> Enclosing' a -> Bool
< :: Enclosing' a -> Enclosing' a -> Bool
$c< :: forall a. Ord a => Enclosing' a -> Enclosing' a -> Bool
compare :: Enclosing' a -> Enclosing' a -> Ordering
$ccompare :: forall a. Ord a => Enclosing' a -> Enclosing' a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Enclosing' a)
Ord)

type Enclosing = Enclosing' ()

pattern FallingEdge :: Enclosing' ()
pattern $bFallingEdge :: Enclosing' ()
$mFallingEdge :: forall r. Enclosing' () -> (Void# -> r) -> (Void# -> r) -> r
FallingEdge = FallingEdgeWith ()

{-# COMPLETE RisingEdge, FallingEdge #-}

-- | Enclose an action using the given 'Tracer'.
encloseWith ::
     Applicative m
  => Tracer m Enclosing
  -> m a
  -> m a
encloseWith :: Tracer m (Enclosing' ()) -> m a -> m a
encloseWith Tracer m (Enclosing' ())
tracer m a
action =
    Tracer m (Enclosing' ()) -> Enclosing' () -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Enclosing' ())
tracer Enclosing' ()
forall a. Enclosing' a
RisingEdge m () -> m a -> m a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> m a
action m a -> m () -> m a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Tracer m (Enclosing' ()) -> Enclosing' () -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (Enclosing' ())
tracer Enclosing' ()
FallingEdge