module Network.Wai.Handler.Warp.MultiMap (
MMap
, isEmpty
, empty
, singleton
, insert
, search
, searchWith
, pruneWith
, toList
, merge
) where
import Data.IntMap.Strict (IntMap)
import qualified Data.IntMap.Strict as I
import qualified Data.List.NonEmpty as NE
import Data.Semigroup
import Prelude
import Network.Wai.Handler.Warp.Imports hiding ((<>), union, empty, insert)
type MMap v = IntMap (NonEmpty v)
isEmpty :: MMap v -> Bool
isEmpty = I.null
empty :: MMap v
empty = I.empty
singleton :: Int -> v -> MMap v
singleton k v = I.singleton k (v :| [])
search :: Int -> MMap v -> Maybe v
search k m = case I.lookup k m of
Nothing -> Nothing
Just s -> Just $! NE.head s
searchWith :: Int -> (v -> Bool) -> MMap v -> Maybe v
searchWith k f m = case I.lookup k m of
Nothing -> Nothing
Just nxs -> find f $ NE.toList nxs
insert :: Int -> v -> MMap v -> MMap v
insert k v m = I.insertWith (<>) k (v :| []) m
toList :: MMap v -> [v]
toList m = concatMap f $ I.toAscList m
where
f (_,s) = NE.toList s
pruneWith :: MMap v
-> (v -> IO Bool)
-> IO (MMap v)
pruneWith m action = I.fromAscList <$> go (I.toDescList m) []
where
go [] acc = return acc
go ((k,s):kss) acc = do
mt <- prune action s
case mt of
Nothing -> go kss acc
Just t -> go kss ((k,t) : acc)
merge :: MMap v -> MMap v -> MMap v
merge m1 m2 = I.unionWith (<>) m1 m2
prune :: (a -> IO Bool) -> NonEmpty a -> IO (Maybe (NonEmpty a))
prune act nxs = NE.nonEmpty <$> go (NE.toList nxs)
where
go [] = return []
go (x:xs) = do
keep <- act x
rs <- go xs
return $ if keep then x:rs else rs