module Network.HTTP2.Client.Channels (
   FramesChan
 , hasStreamId
 , hasTypeId
 , whenFrame
 , whenFrameElse
 -- re-exports
 , module Control.Concurrent.Chan.Lifted
 ) where

import           Control.Concurrent.Chan.Lifted (Chan, readChan, newChan, writeChan)
import           Control.Exception.Lifted (Exception, throwIO)
import           Network.HTTP2 (StreamId, FrameHeader, FramePayload, FrameTypeId, framePayloadToFrameTypeId, streamId)

import           Network.HTTP2.Client.Exceptions

type FramesChan e = Chan (FrameHeader, Either e FramePayload)

whenFrame
  :: Exception e
  => (FrameHeader -> FramePayload -> Bool)
  -> (FrameHeader, Either e FramePayload)
  -> ((FrameHeader, FramePayload) -> ClientIO ())
  -> ClientIO ()
whenFrame :: (FrameHeader -> FramePayload -> Bool)
-> (FrameHeader, Either e FramePayload)
-> ((FrameHeader, FramePayload) -> ClientIO ())
-> ClientIO ()
whenFrame FrameHeader -> FramePayload -> Bool
test (FrameHeader, Either e FramePayload)
frame (FrameHeader, FramePayload) -> ClientIO ()
handle = do
    (FrameHeader -> FramePayload -> Bool)
-> (FrameHeader, Either e FramePayload)
-> ((FrameHeader, FramePayload) -> ClientIO ())
-> ((FrameHeader, FramePayload) -> ClientIO ())
-> ClientIO ()
forall e a.
Exception e =>
(FrameHeader -> FramePayload -> Bool)
-> (FrameHeader, Either e FramePayload)
-> ((FrameHeader, FramePayload) -> ClientIO a)
-> ((FrameHeader, FramePayload) -> ClientIO a)
-> ClientIO a
whenFrameElse FrameHeader -> FramePayload -> Bool
test (FrameHeader, Either e FramePayload)
frame (FrameHeader, FramePayload) -> ClientIO ()
handle (ClientIO () -> (FrameHeader, FramePayload) -> ClientIO ()
forall a b. a -> b -> a
const (ClientIO () -> (FrameHeader, FramePayload) -> ClientIO ())
-> ClientIO () -> (FrameHeader, FramePayload) -> ClientIO ()
forall a b. (a -> b) -> a -> b
$ () -> ClientIO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())

whenFrameElse
  :: Exception e
  => (FrameHeader -> FramePayload -> Bool)
  -> (FrameHeader, Either e FramePayload)
  -> ((FrameHeader, FramePayload) -> ClientIO a)
  -> ((FrameHeader, FramePayload) -> ClientIO a)
  -> ClientIO a
whenFrameElse :: (FrameHeader -> FramePayload -> Bool)
-> (FrameHeader, Either e FramePayload)
-> ((FrameHeader, FramePayload) -> ClientIO a)
-> ((FrameHeader, FramePayload) -> ClientIO a)
-> ClientIO a
whenFrameElse FrameHeader -> FramePayload -> Bool
test (FrameHeader
fHead, Either e FramePayload
fPayload) (FrameHeader, FramePayload) -> ClientIO a
handleTrue (FrameHeader, FramePayload) -> ClientIO a
handleFalse = do
    FramePayload
dat <- (e -> ExceptT ClientError IO FramePayload)
-> (FramePayload -> ExceptT ClientError IO FramePayload)
-> Either e FramePayload
-> ExceptT ClientError IO FramePayload
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either e -> ExceptT ClientError IO FramePayload
forall (m :: * -> *) e a. (MonadBase IO m, Exception e) => e -> m a
throwIO FramePayload -> ExceptT ClientError IO FramePayload
forall (f :: * -> *) a. Applicative f => a -> f a
pure Either e FramePayload
fPayload
    if FrameHeader -> FramePayload -> Bool
test FrameHeader
fHead FramePayload
dat
    then (FrameHeader, FramePayload) -> ClientIO a
handleTrue (FrameHeader
fHead, FramePayload
dat)
    else (FrameHeader, FramePayload) -> ClientIO a
handleFalse (FrameHeader
fHead, FramePayload
dat)

hasStreamId :: StreamId -> FrameHeader -> FramePayload -> Bool
hasStreamId :: StreamId -> FrameHeader -> FramePayload -> Bool
hasStreamId StreamId
sid FrameHeader
h FramePayload
_ = FrameHeader -> StreamId
streamId FrameHeader
h StreamId -> StreamId -> Bool
forall a. Eq a => a -> a -> Bool
== StreamId
sid

hasTypeId :: [FrameTypeId] -> FrameHeader -> FramePayload -> Bool
hasTypeId :: [FrameTypeId] -> FrameHeader -> FramePayload -> Bool
hasTypeId [FrameTypeId]
tids FrameHeader
_ FramePayload
p = FramePayload -> FrameTypeId
framePayloadToFrameTypeId FramePayload
p FrameTypeId -> [FrameTypeId] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FrameTypeId]
tids