82 lines
2.7 KiB
Haskell
82 lines
2.7 KiB
Haskell
-- | Check for overlapping routes.
|
|
module Yesod.Routes.Overlap
|
|
( findOverlaps
|
|
, findOverlapNames
|
|
) where
|
|
|
|
import Yesod.Routes.TH.Types
|
|
import Control.Arrow ((***))
|
|
import Data.Maybe (mapMaybe)
|
|
|
|
findOverlaps :: [Resource t] -> [(Resource t, Resource t)]
|
|
findOverlaps [] = []
|
|
findOverlaps (x:xs) = mapMaybe (findOverlap x) xs ++ findOverlaps xs
|
|
|
|
findOverlap :: Resource t -> Resource t -> Maybe (Resource t, Resource t)
|
|
findOverlap x y
|
|
| overlaps (resourcePieces x) (resourcePieces y) (hasSuffix x) (hasSuffix y) = Just (x, y)
|
|
| otherwise = Nothing
|
|
|
|
hasSuffix :: Resource t -> Bool
|
|
hasSuffix r =
|
|
case resourceDispatch r of
|
|
Subsite{} -> True
|
|
Methods Just{} _ -> True
|
|
Methods Nothing _ -> False
|
|
|
|
overlaps :: [(CheckOverlap, Piece t)] -> [(CheckOverlap, Piece t)] -> Bool -> Bool -> Bool
|
|
|
|
-- No pieces on either side, will overlap regardless of suffix
|
|
overlaps [] [] _ _ = True
|
|
|
|
-- No pieces on the left, will overlap if the left side has a suffix
|
|
overlaps [] _ suffixX _ = suffixX
|
|
|
|
-- Ditto for the right
|
|
overlaps _ [] _ suffixY = suffixY
|
|
|
|
-- As soon as we ignore a single piece (via CheckOverlap == False), we say that
|
|
-- the routes don't overlap at all. In other words, disabling overlap checking
|
|
-- on a single piece disables it on the whole route.
|
|
overlaps ((False, _):_) _ _ _ = False
|
|
overlaps _ ((False, _):_) _ _ = False
|
|
|
|
-- Compare the actual pieces
|
|
overlaps ((True, pieceX):xs) ((True, pieceY):ys) suffixX suffixY =
|
|
piecesOverlap pieceX pieceY && overlaps xs ys suffixX suffixY
|
|
|
|
piecesOverlap :: Piece t -> Piece t -> Bool
|
|
-- Statics only match if they equal. Dynamics match with anything
|
|
piecesOverlap (Static x) (Static y) = x == y
|
|
piecesOverlap _ _ = True
|
|
|
|
findOverlapNames :: [Resource t] -> [(String, String)]
|
|
findOverlapNames = map (resourceName *** resourceName) . findOverlaps
|
|
|
|
{-
|
|
-- n^2, should be a way to speed it up
|
|
findOverlaps :: [Resource a] -> [[Resource a]]
|
|
findOverlaps = go . map justPieces
|
|
where
|
|
justPieces :: Resource a -> ([Piece a], Resource a)
|
|
justPieces r@(Resource _ ps _) = (ps, r)
|
|
|
|
go [] = []
|
|
go (x:xs) = mapMaybe (mOverlap x) xs ++ go xs
|
|
|
|
mOverlap :: ([Piece a], Resource a) -> ([Piece a], Resource a) ->
|
|
Maybe [Resource a]
|
|
mOverlap _ _ = Nothing
|
|
{- FIXME mOverlap
|
|
mOverlap (Static x:xs, xr) (Static y:ys, yr)
|
|
| x == y = mOverlap (xs, xr) (ys, yr)
|
|
| otherwise = Nothing
|
|
mOverlap (MultiPiece _:_, xr) (_, yr) = Just (xr, yr)
|
|
mOverlap (_, xr) (MultiPiece _:_, yr) = Just (xr, yr)
|
|
mOverlap ([], xr) ([], yr) = Just (xr, yr)
|
|
mOverlap ([], _) (_, _) = Nothing
|
|
mOverlap (_, _) ([], _) = Nothing
|
|
mOverlap (_:xs, xr) (_:ys, yr) = mOverlap (xs, xr) (ys, yr)
|
|
-}
|
|
-}
|