module Network.Wai.Handler.Warp.HashMap where

import Data.Hashable (hash)
import Data.IntMap.Strict (IntMap)
import qualified Data.IntMap.Strict as I
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as M
import Prelude hiding (lookup)

----------------------------------------------------------------

-- | 'HashMap' is used for cache of file information.
--   Hash values of file pathes are used as outer keys.
--   Because negative entries are also contained,
--   a bad guy can intentionally cause the hash collison.
--   So, 'Map' is used internally to prevent
--   the hash collision attack.
newtype HashMap v = HashMap (IntMap (Map FilePath v))

----------------------------------------------------------------

empty :: HashMap v
empty :: forall v. HashMap v
empty = forall v. IntMap (Map FilePath v) -> HashMap v
HashMap forall a. IntMap a
I.empty

isEmpty :: HashMap v -> Bool
isEmpty :: forall v. HashMap v -> Bool
isEmpty (HashMap IntMap (Map FilePath v)
hm) = forall a. IntMap a -> Bool
I.null IntMap (Map FilePath v)
hm

----------------------------------------------------------------

insert :: FilePath -> v -> HashMap v -> HashMap v
insert :: forall v. FilePath -> v -> HashMap v -> HashMap v
insert FilePath
path v
v (HashMap IntMap (Map FilePath v)
hm) = forall v. IntMap (Map FilePath v) -> HashMap v
HashMap
  forall a b. (a -> b) -> a -> b
$ forall a. (a -> a -> a) -> Key -> a -> IntMap a -> IntMap a
I.insertWith forall k a. Ord k => Map k a -> Map k a -> Map k a
M.union (forall a. Hashable a => a -> Key
hash FilePath
path) (forall k a. k -> a -> Map k a
M.singleton FilePath
path v
v) IntMap (Map FilePath v)
hm

lookup :: FilePath -> HashMap v -> Maybe v
lookup :: forall v. FilePath -> HashMap v -> Maybe v
lookup FilePath
path (HashMap IntMap (Map FilePath v)
hm) = forall a. Key -> IntMap a -> Maybe a
I.lookup (forall a. Hashable a => a -> Key
hash FilePath
path) IntMap (Map FilePath v)
hm forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup FilePath
path