content: {-# LANGUAGE RecordWildCards #-}
  
  module Network.QUIC.Recovery.PeerPacketNumbers (
      getPeerPacketNumbers,
      addPeerPacketNumbers,
      delPeerPacketNumbers,
      clearPeerPacketNumbers,
      reducePeerPacketNumbers,
      setPreviousRTT1PPNs,
      getPreviousRTT1PPNs,
      nullPeerPacketNumbers,
      fromPeerPacketNumbers,
  ) where
  
  import qualified Data.IntSet as IntSet
  
  import Network.QUIC.Imports hiding (range)
  import Network.QUIC.Recovery.Types
  import Network.QUIC.Types
  
  ----------------------------------------------------------------
  -- Peer's packet numbers
  
  {-# INLINE getPeerPacketNumbers #-}
  getPeerPacketNumbers :: LDCC -> EncryptionLevel -> IO PeerPacketNumbers
  getPeerPacketNumbers LDCC{..} lvl = readIORef (peerPacketNumbers ! lvl)
  
  {-# INLINE addPeerPacketNumbers #-}
  addPeerPacketNumbers :: LDCC -> EncryptionLevel -> PacketNumber -> IO ()
  addPeerPacketNumbers LDCC{..} lvl pn =
      atomicModifyIORef'' (peerPacketNumbers ! lvl) add
    where
      add (PeerPacketNumbers pns) = PeerPacketNumbers $ IntSet.insert pn pns
  
  {-# INLINE delPeerPacketNumbers #-}
  delPeerPacketNumbers :: LDCC -> EncryptionLevel -> PacketNumber -> IO ()
  delPeerPacketNumbers LDCC{..} lvl pn =
      atomicModifyIORef'' (peerPacketNumbers ! lvl) del
    where
      del (PeerPacketNumbers pns) = PeerPacketNumbers $ IntSet.delete pn pns
  
  {-# INLINE clearPeerPacketNumbers #-}
  clearPeerPacketNumbers :: LDCC -> EncryptionLevel -> IO ()
  clearPeerPacketNumbers LDCC{..} lvl =
      atomicModifyIORef'' (peerPacketNumbers ! lvl) $ \_ -> emptyPeerPacketNumbers
  
  {-# INLINE reducePeerPacketNumbers #-}
  reducePeerPacketNumbers :: LDCC -> EncryptionLevel -> PeerPacketNumbers -> IO ()
  reducePeerPacketNumbers LDCC{..} lvl (PeerPacketNumbers pns) =
      atomicModifyIORef'' (peerPacketNumbers ! lvl) reduce
    where
      reduce (PeerPacketNumbers pns0) = PeerPacketNumbers (pns0 IntSet.\\ pns)
  
  {-# INLINE setPreviousRTT1PPNs #-}
  setPreviousRTT1PPNs :: LDCC -> PeerPacketNumbers -> IO ()
  setPreviousRTT1PPNs LDCC{..} ppns = writeIORef previousRTT1PPNs ppns
  
  {-# INLINE getPreviousRTT1PPNs #-}
  getPreviousRTT1PPNs :: LDCC -> IO PeerPacketNumbers
  getPreviousRTT1PPNs LDCC{..} = readIORef previousRTT1PPNs
  
  ----------------------------------------------------------------
  
  {-# INLINE nullPeerPacketNumbers #-}
  nullPeerPacketNumbers :: PeerPacketNumbers -> Bool
  nullPeerPacketNumbers (PeerPacketNumbers pns) = IntSet.null pns
  
  {-# INLINE fromPeerPacketNumbers #-}
  fromPeerPacketNumbers :: PeerPacketNumbers -> [PacketNumber]
  fromPeerPacketNumbers (PeerPacketNumbers pns) = IntSet.toDescList pns
  