, UndecidableInstances
, UnicodeSyntax
#-}
+{-# OPTIONS_GHC -fno-warn-missing-methods #-}
module Network.HTTP.Lucu.Dispatcher.Internal
( SchemeMapper(..)
, SchemeMap
, ResourceMapper(..)
, ResourceMap
, ResourceTree
+ , ResourceNode
, dispatch
)
import Control.Monad.Trans.Maybe
import Control.Monad.Unicode
import Data.Collections
-import qualified Data.Collections.Newtype.TH as C
+import qualified Data.Map as M
import Data.Monoid
import Data.Monoid.Unicode
-import Network.HTTP.Lucu.Dispatcher.Node
import Network.HTTP.Lucu.Resource.Internal
import Network.HTTP.Lucu.Utils
import Network.URI hiding (path)
-import Prelude hiding (lookup)
+import Prelude hiding (filter, lookup, null)
import Prelude.Unicode
-- |FIXME: docs
-- |Container type for the 'ResourceMapper' type class.
data ResourceMap = ∀α. ResourceMapper α ⇒ RMap α
--- FIXME: doc
+-- |FIXME: doc
newtype ResourceTree = Root ResourceNode
deriving (Monoid, Show)
+-- |FIXME: docs
+data ResourceNode
+ = Greedy !Resource
+ | NonGreedy !Resource !SubTree
+ | Branch !SubTree
+
+type SubTree
+ = M.Map PathSegment ResourceNode
+
-- Instances of SchemeMapper --------------------------------------------------
instance SchemeMapper SchemeMap where
{-# INLINE findHostMap #-}
{-# INLINE mappend #-}
mappend = insert
+-- |Any 'Map's from 'Scheme' to 'HostMap' are also 'SchemeMapper's.
instance Map α Scheme HostMap ⇒ SchemeMapper α where
{-# INLINE findHostMap #-}
findHostMap = (maybe (fail (⊥)) return ∘) ∘ lookup
{-# INLINE mappend #-}
mappend = insert
+-- |Any 'Map's from 'Host' to 'ResourceMap' are also 'HostMapper's.
instance Map α Host ResourceMap ⇒ HostMapper α where
{-# INLINE findResourceMap #-}
findResourceMap = (maybe (fail (⊥)) return ∘) ∘ lookup
{-# INLINE mappend #-}
mappend = insert
+-- |Any 'Map's from 'PathSegments' to @('PathSegments', 'Resource')@
+-- are also 'ResourceMapper's.
instance Map α PathSegments (PathSegments, Resource) ⇒ ResourceMapper α where
{-# INLINE findResource #-}
findResource = (maybe (fail (⊥)) return ∘) ∘ lookup
findResource = (maybe (fail (⊥)) return ∘) ∘ flip id
-- Instances of ResourceTree --------------------------------------------------
-C.derive [d| instance Foldable ResourceTree (PathSegments, ResourceNode)
- |]
+instance Unfoldable ResourceTree (PathSegments, ResourceNode) where
+ {-# INLINEABLE insert #-}
+ insert (p, a) (Root b) = Root $ insertNodeAt (canonPath p) a b
+ {-# INLINE empty #-}
+ empty = Root $ Branch (∅)
+
+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 ) = f (p, Greedy r)
+ go p (NonGreedy r m) = f (p, NonGreedy r (∅)) ⊕ go' p m
+ 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
+
+
+-- Instances of ResourceNode --------------------------------------------------
+instance Show ResourceNode where
+ show (Greedy _ ) = "Greedy _"
+ 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 ) _ = Greedy r
+ mappend (NonGreedy r m) (Greedy _ ) = NonGreedy r m
+ mappend (NonGreedy r m) (NonGreedy _ n) = NonGreedy r (m ⊕ n)
+ mappend (NonGreedy r m) (Branch n) = NonGreedy r (m ⊕ n)
+ mappend (Branch _) (Greedy r ) = Greedy r
+ mappend (Branch m) (NonGreedy r n) = NonGreedy r (m ⊕ n)
+ mappend (Branch m) (Branch n) = Branch (m ⊕ n)
-- dispatch -------------------------------------------------------------------
dispatch ∷ SchemeMapper α ⇒ URI → α → MaybeT IO (PathSegments, Resource)
+++ /dev/null
-{-# LANGUAGE
- FlexibleInstances
- , MultiParamTypeClasses
- , UnicodeSyntax
- #-}
-module Network.HTTP.Lucu.Dispatcher.Node
- ( ResourceNode
- )
- where
-import Data.Collections
-import qualified Data.Map as M
-import Data.Monoid
-import Data.Monoid.Unicode
-import Network.HTTP.Lucu.Resource.Internal
-import Network.HTTP.Lucu.Utils
-import Prelude hiding (filter, null)
-import Prelude.Unicode
-
--- FIXME: docs
-data ResourceNode
- = Greedy !Resource
- | NonGreedy !Resource !SubTree
- | Branch !SubTree
-
-type SubTree
- = M.Map PathSegment ResourceNode
-
-instance Show ResourceNode where
- show (Greedy _ ) = "Greedy _"
- 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 ) _ = Greedy r
- mappend (NonGreedy r m) (Greedy _ ) = NonGreedy r m
- mappend (NonGreedy r m) (NonGreedy _ n) = NonGreedy r (m ⊕ n)
- mappend (NonGreedy r m) (Branch n) = NonGreedy r (m ⊕ n)
- mappend (Branch _) (Greedy r ) = Greedy r
- mappend (Branch m) (NonGreedy r n) = NonGreedy r (m ⊕ n)
- mappend (Branch m) (Branch n) = Branch (m ⊕ n)
-
-instance Unfoldable ResourceNode (PathSegments, ResourceNode) where
- {-# INLINEABLE insert #-}
- insert (p, n) = insertNodeAt (canonPath p) n
- {-# INLINE empty #-}
- empty = Branch (∅)
-
-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 ResourceNode (PathSegments, ResourceNode) where
- foldMap f = go (∅)
- where
- go p (Greedy r ) = f (p, Greedy r)
- go p (NonGreedy r m) = f (p, NonGreedy r (∅)) ⊕ go' p m
- go p (Branch m) = go' p m
-
- go' p = foldMap $ \(s, n) → go (p `snoc` s) n
-
- null (Greedy _ ) = False
- null (NonGreedy _ _) = False
- null (Branch m) = null m