1 module Snap.Util.Readable
    2   ( Readable(..)
    3   ) where
    4 
    5 ------------------------------------------------------------------------------
    6 import           Data.ByteString.Char8 (ByteString)
    7 import           Data.Text (Text)
    8 import qualified Data.Text as T
    9 import           Data.Text.Encoding
   10 import           Data.Text.Read
   11 
   12 
   13 ------------------------------------------------------------------------------
   14 -- | Runs a 'Snap' monad action only when 'rqPathInfo' is empty.
   15 class Readable a where
   16     fromBS :: Monad m => ByteString -> m a
   17 
   18 
   19 ------------------------------------------------------------------------------
   20 -- | Fails if the input wasn't parsed completely.
   21 checkComplete :: Monad m => (t, Text) -> m t
   22 checkComplete (a,rest)
   23   | T.null rest = return a
   24   | otherwise   = fail "Readable: could not parse completely"
   25 
   26 
   27 instance Readable ByteString where
   28     fromBS = return
   29 instance Readable Text where
   30     fromBS = return . decodeUtf8
   31 instance Readable Int where
   32     fromBS = either fail checkComplete . decimal . decodeUtf8
   33 instance Readable Integer where
   34     fromBS = either fail checkComplete . decimal . decodeUtf8
   35 instance Readable Double where
   36     fromBS = either fail checkComplete . double . decodeUtf8