]> gitweb @ CieloNegro.org - Lucu.git/commitdiff
Simplify the implementation of ResourceTree
authorPHO <pho@cielonegro.org>
Thu, 24 Nov 2011 12:33:08 +0000 (21:33 +0900)
committerPHO <pho@cielonegro.org>
Thu, 24 Nov 2011 12:33:08 +0000 (21:33 +0900)
Ditz-issue: e0312227f40a0fa92d4c5d69a64dad473f54389a

Network/HTTP/Lucu/Dispatcher.hs
Network/HTTP/Lucu/Dispatcher/Internal.hs

index 67838b03be91987b6e31d34b56039f4efca81141..7b0c84003a2c84c14b67184b05a75b3b4dbc55d5 100644 (file)
@@ -8,6 +8,8 @@ module Network.HTTP.Lucu.Dispatcher
     , ResourceMap
     , ResourceTree
     , ResourceNode
+    , greedy
+    , nonGreedy
     )
     where
 import Network.HTTP.Lucu.Dispatcher.Internal
index 6cb741d55f62dbd26a9c80cb80b4d211144d98e7..c889fc51dfae6683f2a6b10890ac7178f5860459 100644 (file)
@@ -1,17 +1,14 @@
 {-# LANGUAGE
-    DoAndIfThenElse
-  , ExistentialQuantification
+    ExistentialQuantification
+  , FlexibleContexts
   , FlexibleInstances
   , GeneralizedNewtypeDeriving
   , OverlappingInstances
   , MultiParamTypeClasses
-  , RecordWildCards
-  , ScopedTypeVariables
   , TemplateHaskell
   , UndecidableInstances
   , UnicodeSyntax
   #-}
-{-# OPTIONS_GHC -fno-warn-missing-methods #-}
 module Network.HTTP.Lucu.Dispatcher.Internal
     ( SchemeMapper(..)
     , SchemeMap
@@ -21,6 +18,8 @@ module Network.HTTP.Lucu.Dispatcher.Internal
     , ResourceMap
     , ResourceTree
     , ResourceNode
+    , greedy
+    , nonGreedy
 
     , dispatch
     )
@@ -75,17 +74,23 @@ class ResourceMapper α where
 data ResourceMap = ∀α. ResourceMapper α ⇒ RMap α
 
 -- |FIXME: doc
-newtype ResourceTree = Root ResourceNode
-    deriving (Monoid, Show)
+newtype ResourceTree = Tree (M.Map PathSegments ResourceNode)
+    deriving Monoid
 
--- |FIXME: docs
+-- |FIXME: doc
 data ResourceNode
-    = Greedy    !Resource !SubTree
-    | NonGreedy !Resource !SubTree
-    | Branch              !SubTree
+    = Greedy    { nResource ∷ !Resource }
+    | NonGreedy { nResource ∷ !Resource }
 
-type SubTree
-    = M.Map PathSegment ResourceNode
+-- |FIXME: doc
+greedy ∷ Resource → ResourceNode
+{-# INLINE CONLIKE greedy #-}
+greedy = Greedy
+
+-- |FIXME: doc
+nonGreedy ∷ Resource → ResourceNode
+{-# INLINE CONLIKE nonGreedy #-}
+nonGreedy = NonGreedy
 
 -- Instances of SchemeMapper --------------------------------------------------
 instance SchemeMapper SchemeMap where
@@ -252,58 +257,36 @@ instance ResourceMapper (PathSegments → Maybe (PathSegments, Resource)) where
 -- Instances of ResourceTree --------------------------------------------------
 instance Unfoldable ResourceTree (PathSegments, ResourceNode) where
     {-# INLINEABLE insert #-}
-    insert (p, a) (Root b) = Root $ insertNodeAt (canonPath p) a b
+    insert (p, n) (Tree m) = Tree $ insert (canonPath p, n) m
     {-# INLINE empty #-}
-    empty = Root $ Branch (∅)
+    empty = Tree (∅)
+    {-# INLINE singleton #-}
+    singleton = Tree ∘ singleton
 
 canonPath ∷ (Collection c f, Foldable f e) ⇒ c → c
 {-# INLINEABLE canonPath #-}
 canonPath = filter ((¬) ∘ null)
 
-insertNodeAt ∷ PathSegments → ResourceNode → ResourceNode → ResourceNode
-{-# INLINEABLE insertNodeAt #-}
-insertNodeAt p a b
-    = case front p of
-        Nothing         → a ⊕ b
-        Just (x, xs)
-            | null xs   → Branch (singleton (x, a)) ⊕ b
-            | otherwise → insertNodeAt xs a (∅) ⊕ b
-
-instance Foldable ResourceTree (PathSegments, ResourceNode) where
-    foldMap f (Root n) = go (∅) n
-        where
-          go p (Greedy    r m) = go' p m ⊕ f (p, Greedy    r (∅))
-          go p (NonGreedy r m) = go' p m ⊕ f (p, NonGreedy r (∅))
-          go p (Branch      m) = go' p m
-
-          go' p = foldMap $ \(s, n') → go (p `snoc` s) n'
-
-    null (Root (Greedy    _ _)) = False
-    null (Root (NonGreedy _ _)) = False
-    null (Root (Branch      m)) = null m
-
-instance Collection ResourceTree (PathSegments, ResourceNode) where
-    {-# INLINE filter #-}
-    filter f = fromList ∘ filter f ∘ fromFoldable
-
-
--- Instances of ResourceNode --------------------------------------------------
-instance Show ResourceNode where
-    show (Greedy    _ m) = "Greedy _ " ⊕ show m
-    show (NonGreedy _ m) = "NonGreedy _ " ⊕ show m
-    show (Branch      m) = "Branch " ⊕ show m
-
-instance Monoid ResourceNode where
-    {-# INLINE mempty #-}
-    mempty = Branch (∅)
-    {-# INLINEABLE mappend #-}
-    mappend (Greedy    r m) _               = Greedy    r      m
-    mappend (NonGreedy r m) (Greedy    _ n) = NonGreedy r (m ⊕ n)
-    mappend (NonGreedy r m) (NonGreedy _ n) = NonGreedy r (m ⊕ n)
-    mappend (NonGreedy r m) (Branch      n) = NonGreedy r (m ⊕ n)
-    mappend (Branch      m) (Greedy    r n) = Greedy    r (m ⊕ n)
-    mappend (Branch      m) (NonGreedy r n) = NonGreedy r (m ⊕ n)
-    mappend (Branch      m) (Branch      n) = Branch      (m ⊕ n)
+-- |'findResource' performs the longest prefix match on the tree,
+-- finding the most specific one.
+instance ResourceMapper ResourceTree where
+    {-# INLINEABLE findResource #-}
+    findResource p (Tree m)
+        = case lookup p m of
+            Just n  → return (p, nResource n)
+            Nothing → findGreedyResource p m
+
+findGreedyResource ∷ (Monad m, Map α PathSegments ResourceNode)
+                   ⇒ PathSegments
+                   → α
+                   → MaybeT m (PathSegments, Resource)
+findGreedyResource p m
+    = case back p of
+        Nothing      → fail (⊥)
+        Just (p', _) → case lookup p' m of
+                          Just (Greedy r)
+                              → return (p', r)
+                          _   → findGreedyResource p' m
 
 -- dispatch -------------------------------------------------------------------
 dispatch ∷ SchemeMapper α ⇒ URI → α → MaybeT IO (PathSegments, Resource)