warp 3.3.17 → 3.3.18
raw patch · 5 files changed
+33/−86 lines, 5 filesdep ~ghc-primdep ~unix
Dependency ranges changed: ghc-prim, unix
Files
- ChangeLog.md +5/−0
- Network/Wai/Handler/Warp/HashMap.hs +3/−8
- Network/Wai/Handler/Warp/MultiMap.hs +23/−43
- Network/Wai/Handler/Warp/ReadInt.hs +1/−34
- warp.cabal +1/−1
ChangeLog.md view
@@ -1,5 +1,10 @@ # ChangeLog for warp +## 3.3.18++* Tidy up HashMap and MultiMap [#864](https://github.com/yesodweb/wai/pull/864)+* Support GHC 9.2 [#863](https://github.com/yesodweb/wai/pull/863)+ ## 3.3.17 * Modify exception handling to swallow async exceptions in forked thread [#850](https://github.com/yesodweb/wai/issues/850)
Network/Wai/Handler/Warp/HashMap.hs view
@@ -30,13 +30,8 @@ ---------------------------------------------------------------- insert :: FilePath -> v -> HashMap v -> HashMap v-insert path v (HashMap hm) = HashMap $ I.insertWith f h m hm- where- !h = hash path- !m = M.singleton path v- f = M.union -- fimxe+insert path v (HashMap hm) = HashMap+ $ I.insertWith M.union (hash path) (M.singleton path v) hm lookup :: FilePath -> HashMap v -> Maybe v-lookup path (HashMap hm) = I.lookup h hm >>= M.lookup path- where- !h = hash path+lookup path (HashMap hm) = I.lookup (hash path) hm >>= M.lookup path
Network/Wai/Handler/Warp/MultiMap.hs view
@@ -12,6 +12,7 @@ , merge ) where +import Control.Monad (filterM) import Data.Hashable (hash) import Data.IntMap.Strict (IntMap) import qualified Data.IntMap.Strict as I@@ -20,14 +21,14 @@ ---------------------------------------------------------------- --- | 'MultiMap' is used for cache of file descriptors.--- Since multiple threads would open file descriptors for--- the same file simultaneously, multiple entries must--- be contained for the file.--- Since hash values of file pathes are used as outer keys,--- collison would happen for multiple file pathes.--- Becase only positive entries are contained,--- a bad guy cannot be cause the hash collision intentinally.+-- | 'MultiMap' is used as a cache of file descriptors.+-- Since multiple threads could open file descriptors for+-- the same file simultaneously, there could be multiple entries+-- for one file.+-- Since hash values of file paths are used as outer keys,+-- collison would happen for multiple file paths.+-- Because only positive entries are stored,+-- Malicious attack cannot cause the inner list to blow up. -- So, lists are good enough. newtype MultiMap v = MultiMap (IntMap [(FilePath,v)]) @@ -35,7 +36,7 @@ -- | O(1) empty :: MultiMap v-empty = MultiMap $ I.empty+empty = MultiMap I.empty -- | O(1) isEmpty :: MultiMap v -> Bool@@ -45,29 +46,22 @@ -- | O(1) singleton :: FilePath -> v -> MultiMap v-singleton path v = MultiMap mm- where- !h = hash path- !mm = I.singleton h [(path,v)]+singleton path v = MultiMap $ I.singleton (hash path) [(path,v)] ---------------------------------------------------------------- --- | O(N)+-- | O(M) where M is the number of entries per file lookup :: FilePath -> MultiMap v -> Maybe v-lookup path (MultiMap mm) = case I.lookup h mm of+lookup path (MultiMap mm) = case I.lookup (hash path) mm of Nothing -> Nothing Just s -> Prelude.lookup path s- where- !h = hash path ---------------------------------------------------------------- -- | O(log n) insert :: FilePath -> v -> MultiMap v -> MultiMap v-insert path v (MultiMap mm) = MultiMap mm'- where- !h = hash path- !mm' = I.insertWith (<>) h [(path,v)] mm+insert path v (MultiMap mm) = MultiMap+ $ I.insertWith (<>) (hash path) [(path,v)] mm ---------------------------------------------------------------- @@ -81,31 +75,17 @@ pruneWith :: MultiMap v -> ((FilePath,v) -> IO Bool) -> IO (MultiMap v)-pruneWith (MultiMap mm) action = MultiMap <$> mm'+pruneWith (MultiMap mm) action+ = I.foldrWithKey go (pure . MultiMap) mm I.empty where- !mm' = I.fromAscList <$> go (I.toDescList mm) []- go [] !acc = return acc- go ((h,s):kss) !acc = do- rs <- prune action s- case rs of- [] -> go kss acc- _ -> go kss ((h,rs) : acc)+ go h s cont acc = do+ rs <- filterM action s+ case rs of+ [] -> cont acc+ _ -> cont $! I.insert h rs acc ---------------------------------------------------------------- -- O(n + m) where N is the size of the second argument merge :: MultiMap v -> MultiMap v -> MultiMap v-merge (MultiMap m1) (MultiMap m2) = MultiMap mm- where- !mm = I.unionWith (<>) m1 m2--------------------------------------------------------------------prune :: ((FilePath,v) -> IO Bool) -> [(FilePath,v)] -> IO [(FilePath,v)]-prune action xs0 = go xs0- where- go [] = return []- go (x:xs) = do- keep <- action x- rs <- go xs- return $ if keep then x:rs else rs+merge (MultiMap m1) (MultiMap m2) = MultiMap $ I.unionWith (<>) m1 m2
Network/Wai/Handler/Warp/ReadInt.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE MagicHash #-} {-# LANGUAGE BangPatterns #-} -- Copyright : Erik de Castro Lopo <erikd@mega-nerd.com>@@ -10,13 +9,7 @@ , readInt64 ) where --- This function lives in its own file because the MagicHash pragma interacts--- poorly with the CPP pragma.- import qualified Data.ByteString as S-import GHC.Prim-import GHC.Types-import GHC.Word import Network.Wai.Handler.Warp.Imports hiding (readInt) @@ -34,34 +27,8 @@ {-# NOINLINE readInt64 #-} readInt64 :: ByteString -> Int64-readInt64 bs = S.foldl' (\ !i !c -> i * 10 + fromIntegral (mhDigitToInt c)) 0+readInt64 bs = S.foldl' (\ !i !c -> i * 10 + fromIntegral (c - 48)) 0 $ S.takeWhile isDigit bs--data Table = Table !Addr#--{-# NOINLINE mhDigitToInt #-}-mhDigitToInt :: Word8 -> Int-mhDigitToInt (W8# i) = I# (word2Int# (indexWord8OffAddr# addr (word2Int# i)))- where- !(Table addr) = table- table :: Table- table = Table- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\- \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"# isDigit :: Word8 -> Bool isDigit w = w >= 48 && w <= 57
warp.cabal view
@@ -1,5 +1,5 @@ Name: warp-Version: 3.3.17+Version: 3.3.18 Synopsis: A fast, light-weight web server for WAI applications. License: MIT License-file: LICENSE