{-# LANGUAGE TypeOperators #-} module Network.Protocol.Uri.Encode where import Data.Bits import Data.Char import Data.Maybe import Data.Record.Label import Network.Protocol.Uri.Chars import qualified Data.ByteString as B import qualified Data.ByteString.UTF8 as U -- | URI encode a string. encode :: String -> String encode = concatMap encodeChr where encodeChr c | unreserved c || genDelims c || subDelims c = [c] | otherwise = '%' : intToDigit (shiftR (ord c) 4) : intToDigit ((ord c) .&. 0x0F) : [] -- | URI decode a string. decode :: String -> String decode = U.toString . B.pack . map (fromIntegral . ord) . dec where dec [] = [] dec ('%':d:e:ds) | isHexDigit d && isHexDigit e = (chr $ digs d * 16 + digs e) : dec ds where digs a = fromJust $ lookup (toLower a) $ zip "0123456789abcdef" [0..] dec (d:ds) = d : dec ds -- | Decoding and encoding as a label. encoded :: String :<->: String encoded = decode <-> encode