Commits

Bryan O'Sullivan  committed 17d6f9b

Simplify error handling in URL unescaping

  • Participants
  • Parent commits 01ceb76

Comments (0)

Files changed (2)

   
   build-depends:       
     aeson == 0.2.*,
-    attoparsec >= 0.8.4.0,
+    attoparsec >= 0.8.5.0,
     base == 4.*,
     binary,
+    blaze-builder,
     bytestring,
     containers,
     hashable,

File src/Network/Riak/Escape.hs

 
 import Blaze.ByteString.Builder (fromByteString, toByteString)
 import Blaze.ByteString.Builder.Word (fromWord8)
-import Control.Applicative ((<$>), (<|>))
+import Control.Applicative ((<$>))
 import Data.Attoparsec as A
 import Data.Bits ((.|.), (.&.), shiftL, shiftR)
 import Data.ByteString (ByteString)
         | otherwise = fromWord8 (n + 87)
 
 -- | URL-unescape a string.
-unescape :: ByteString -> Either String ByteString
-unescape s = eitherResult $ parse p s `feed` B.empty
+unescapeP :: Parser ByteString
+unescapeP = toByteString <$> go mempty
   where
-    p = toByteString <$> go (Right mempty)
-    go (Right acc)  = do
+    go acc  = do
       s <- A.takeWhile $ \w -> w /= 37 && w /= 43
       let rest = do
             w <- anyWord8
             if w == 43
-              then go (Right (acc `mappend` fromByteString s `mappend`
-                              fromWord8 32))
-              else flip (<|>) (go (Left "short escape")) $ do
+              then go (acc `mappend` fromByteString s `mappend` fromWord8 32)
+              else do
                 h <- A.take 2
-                let hex w | w >= 48 && w <= 57  = w - 48
-                          | w >= 97 && w <= 102 = w - 87
-                          | w >= 65 && w <= 70  = w - 55
+                let hex b | b >= 48 && b <= 57  = b - 48
+                          | b >= 97 && b <= 102 = b - 87
+                          | b >= 65 && b <= 70  = b - 55
                           | otherwise           = 255
                     hi = hex (B.unsafeIndex h 0)
                     lo = hex (B.unsafeIndex h 1)
                 if hi .|. lo == 255
-                  then go (Left "invalid hex escape")
-                  else go (Right (acc `mappend` fromByteString s `mappend`
-                                  fromWord8 (lo .|. (hi `shiftL` 4))))
-      rest <|> return (acc `mappend` fromByteString s)
-    go (Left err) = fail err
+                  then fail "invalid hex escape"
+                  else go (acc `mappend` fromByteString s `mappend`
+                           fromWord8 (lo .|. (hi `shiftL` 4)))
+      done <- atEnd
+      if done
+        then return (acc `mappend` fromByteString s)
+        else rest
+
+-- | URL-unescape a string.
+unescape :: ByteString -> Either String ByteString
+unescape s0 = eitherResult $ parse unescapeP s0 `feed` B.empty