{-# LANGUAGE CPP #-}
module Network.HTTP.Media.Language.Internal
( Language (..)
) where
#if !MIN_VERSION_base(4, 8, 0)
import Data.Functor ((<$>))
#endif
import qualified Data.ByteString.Char8 as BS
import qualified Data.CaseInsensitive as CI
import Control.Monad (guard)
import Data.ByteString (ByteString)
import Data.CaseInsensitive (CI, original)
import Data.Char (isAlpha)
import Data.List (isPrefixOf)
import Data.Maybe (fromMaybe)
import Data.String (IsString (..))
import Network.HTTP.Media.Accept (Accept (..))
import Network.HTTP.Media.RenderHeader (RenderHeader (..))
newtype Language = Language [CI ByteString]
deriving (Eq, Ord)
instance Show Language where
show = BS.unpack . renderHeader
instance IsString Language where
fromString "*" = Language []
fromString str = flip fromMaybe (parseAccept $ BS.pack str) $
error $ "Invalid language literal " ++ str
instance Accept Language where
parseAccept "*" = Just $ Language []
parseAccept bs = do
let pieces = BS.split '-' bs
guard $ not (null pieces)
Language <$> mapM check pieces
where
check part = do
let len = BS.length part
guard $ len >= 1 && len <= 8 && BS.all isAlpha part
return (CI.mk part)
matches (Language a) (Language b) = b `isPrefixOf` a
moreSpecificThan (Language a) (Language b) =
b `isPrefixOf` a && length a > length b
instance RenderHeader Language where
renderHeader (Language []) = "*"
renderHeader (Language l) = BS.intercalate "-" (map original l)