{-# LANGUAGE RecordWildCards #-}

module Network.HTTP2.Arch.Cache where

import Data.OrdPSQ (OrdPSQ)
import qualified Data.OrdPSQ as PSQ

type Priority = Int

data Cache k v = Cache {
    Cache k v -> Int
cLimit :: Int
  , Cache k v -> Int
cSize  :: Int
  , Cache k v -> Int
cTick  :: Priority
  , Cache k v -> OrdPSQ k Int v
cQueue :: OrdPSQ k Priority v
  }

emptyCache :: Int -> Cache k v
emptyCache :: Int -> Cache k v
emptyCache Int
lim = Int -> Int -> Int -> OrdPSQ k Int v -> Cache k v
forall k v. Int -> Int -> Int -> OrdPSQ k Int v -> Cache k v
Cache Int
lim Int
0 Int
0 OrdPSQ k Int v
forall k p v. OrdPSQ k p v
PSQ.empty

insert :: Ord k => k -> v -> Cache k v -> Cache k v
insert :: k -> v -> Cache k v -> Cache k v
insert k
k v
v c :: Cache k v
c@Cache{Int
OrdPSQ k Int v
cQueue :: OrdPSQ k Int v
cTick :: Int
cSize :: Int
cLimit :: Int
cQueue :: forall k v. Cache k v -> OrdPSQ k Int v
cTick :: forall k v. Cache k v -> Int
cSize :: forall k v. Cache k v -> Int
cLimit :: forall k v. Cache k v -> Int
..}
  | Int
cSize Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
cLimit = let q :: OrdPSQ k Int v
q = k -> Int -> v -> OrdPSQ k Int v -> OrdPSQ k Int v
forall k p v.
(Ord k, Ord p) =>
k -> p -> v -> OrdPSQ k p v -> OrdPSQ k p v
PSQ.insert k
k Int
cTick v
v (OrdPSQ k Int v -> OrdPSQ k Int v)
-> OrdPSQ k Int v -> OrdPSQ k Int v
forall a b. (a -> b) -> a -> b
$ OrdPSQ k Int v -> OrdPSQ k Int v
forall k p v. (Ord k, Ord p) => OrdPSQ k p v -> OrdPSQ k p v
PSQ.deleteMin OrdPSQ k Int v
cQueue
                      in Cache k v
c { cTick :: Int
cTick = Int
cTick Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, cQueue :: OrdPSQ k Int v
cQueue = OrdPSQ k Int v
q }
  | Bool
otherwise       = let q :: OrdPSQ k Int v
q = k -> Int -> v -> OrdPSQ k Int v -> OrdPSQ k Int v
forall k p v.
(Ord k, Ord p) =>
k -> p -> v -> OrdPSQ k p v -> OrdPSQ k p v
PSQ.insert k
k Int
cTick v
v OrdPSQ k Int v
cQueue
                      in Cache k v
c { cTick :: Int
cTick = Int
cTick Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, cQueue :: OrdPSQ k Int v
cQueue = OrdPSQ k Int v
q, cSize :: Int
cSize = Int
cSize Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 }

lookup :: Ord k => k -> Cache k v -> Maybe v
lookup :: k -> Cache k v -> Maybe v
lookup k
k Cache{Int
OrdPSQ k Int v
cQueue :: OrdPSQ k Int v
cTick :: Int
cSize :: Int
cLimit :: Int
cQueue :: forall k v. Cache k v -> OrdPSQ k Int v
cTick :: forall k v. Cache k v -> Int
cSize :: forall k v. Cache k v -> Int
cLimit :: forall k v. Cache k v -> Int
..} = (Int, v) -> v
forall a b. (a, b) -> b
snd ((Int, v) -> v) -> Maybe (Int, v) -> Maybe v
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> k -> OrdPSQ k Int v -> Maybe (Int, v)
forall k p v. Ord k => k -> OrdPSQ k p v -> Maybe (p, v)
PSQ.lookup k
k OrdPSQ k Int v
cQueue