{-# options_haddock prune #-}
-- |Description: Queue Combinators
module Polysemy.Conc.Queue (
  module Polysemy.Conc.Queue,
  module Polysemy.Conc.Effect.Queue,
  module Polysemy.Conc.Data.QueueResult,
) where

import Polysemy.Conc.Data.QueueResult
import qualified Polysemy.Conc.Data.QueueResult as QueueResult
import qualified Polysemy.Conc.Effect.Queue as Queue
import Polysemy.Conc.Effect.Queue (
  Queue,
  close,
  closed,
  peek,
  read,
  readTimeout,
  tryPeek,
  tryRead,
  tryWrite,
  write,
  writeTimeout,
  )
import Polysemy.Conc.Queue.Result (resultToMaybe)

-- |Read from a 'Queue' repeatedly until it is closed.
--
-- When an element is received, call @action@ and recurse if it returns 'True'.
-- When no element is available, evaluate @na@ and recurse if it returns 'True'.
loopOr ::
  Member (Queue d) r =>
  Sem r Bool ->
  (d -> Sem r Bool) ->
  Sem r ()
loopOr :: forall d (r :: EffectRow).
Member (Queue d) r =>
Sem r Bool -> (d -> Sem r Bool) -> Sem r ()
loopOr Sem r Bool
na d -> Sem r Bool
action =
  Sem r ()
spin
  where
    spin :: Sem r ()
spin =
      Sem r (QueueResult d)
forall d (r :: EffectRow).
Member (Queue d) r =>
Sem r (QueueResult d)
Queue.read Sem r (QueueResult d) -> (QueueResult d -> Sem r ()) -> Sem r ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
        QueueResult.Success d
d -> Sem r Bool -> Sem r () -> Sem r ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
whenM (d -> Sem r Bool
action d
d) Sem r ()
spin
        QueueResult d
QueueResult.NotAvailable -> Sem r Bool -> Sem r () -> Sem r ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
whenM Sem r Bool
na Sem r ()
spin
        QueueResult d
QueueResult.Closed -> Sem r ()
forall (f :: * -> *). Applicative f => f ()
unit

-- |Read from a 'Queue' repeatedly until it is closed.
--
-- When an element is received, call @action@ and recurse.
loop ::
  Member (Queue d) r =>
  (d -> Sem r ()) ->
  Sem r ()
loop :: forall d (r :: EffectRow).
Member (Queue d) r =>
(d -> Sem r ()) -> Sem r ()
loop d -> Sem r ()
action =
  Sem r Bool -> (d -> Sem r Bool) -> Sem r ()
forall d (r :: EffectRow).
Member (Queue d) r =>
Sem r Bool -> (d -> Sem r Bool) -> Sem r ()
loopOr (Bool -> Sem r Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True) \ d
d -> Bool
True Bool -> Sem r () -> Sem r Bool
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ d -> Sem r ()
action d
d

-- |Read from a 'Queue' and convert the result to 'Maybe', returning 'Nothing' if the queue has been closed, and
-- blocking until an element is available.
readMaybe ::
  Member (Queue d) r =>
  Sem r (Maybe d)
readMaybe :: forall d (r :: EffectRow). Member (Queue d) r => Sem r (Maybe d)
readMaybe =
  QueueResult d -> Maybe d
forall d. QueueResult d -> Maybe d
resultToMaybe (QueueResult d -> Maybe d)
-> Sem r (QueueResult d) -> Sem r (Maybe d)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sem r (QueueResult d)
forall d (r :: EffectRow).
Member (Queue d) r =>
Sem r (QueueResult d)
read

-- |Read from a 'Queue' and convert the result to 'Maybe', returning 'Nothing' if there is no element available or the
-- queue has been closed.
tryReadMaybe ::
  Member (Queue d) r =>
  Sem r (Maybe d)
tryReadMaybe :: forall d (r :: EffectRow). Member (Queue d) r => Sem r (Maybe d)
tryReadMaybe =
  QueueResult d -> Maybe d
forall d. QueueResult d -> Maybe d
resultToMaybe (QueueResult d -> Maybe d)
-> Sem r (QueueResult d) -> Sem r (Maybe d)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sem r (QueueResult d)
forall d (r :: EffectRow).
Member (Queue d) r =>
Sem r (QueueResult d)
tryRead