packages feed

attoparsec-uri 0.0.1 → 0.0.2

raw patch · 4 files changed

+68/−147 lines, 4 filesdep +attoparsec-ipdep +ipdep −n-tuplePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: attoparsec-ip, ip

Dependencies removed: n-tuple

API changes (from Hackage documentation)

- Data.URI: instance (Data.Data.Data a, Data.Data.Data b) => Data.Data.Data (Data.Strict.Tuple.Pair a b)
- Data.URI: instance Data.Data.Data Data.URI.URI
- Data.URI: instance GHC.Generics.Constructor Data.URI.C1_0URI
- Data.URI: instance GHC.Generics.Datatype Data.URI.D1URI
- Data.URI: instance GHC.Generics.Selector Data.URI.S1_0_0URI
- Data.URI: instance GHC.Generics.Selector Data.URI.S1_0_1URI
- Data.URI: instance GHC.Generics.Selector Data.URI.S1_0_2URI
- Data.URI: instance GHC.Generics.Selector Data.URI.S1_0_3URI
- Data.URI: instance GHC.Generics.Selector Data.URI.S1_0_4URI
- Data.URI: instance GHC.Generics.Selector Data.URI.S1_0_5URI
- Data.URI.Auth: instance Data.Data.Data Data.URI.Auth.URIAuth
- Data.URI.Auth: instance Data.Data.Data a => Data.Data.Data (Data.Strict.Maybe.Maybe a)
- Data.URI.Auth: instance GHC.Generics.Constructor Data.URI.Auth.C1_0URIAuth
- Data.URI.Auth: instance GHC.Generics.Datatype Data.URI.Auth.D1URIAuth
- Data.URI.Auth: instance GHC.Generics.Selector Data.URI.Auth.S1_0_0URIAuth
- Data.URI.Auth: instance GHC.Generics.Selector Data.URI.Auth.S1_0_1URIAuth
- Data.URI.Auth: instance GHC.Generics.Selector Data.URI.Auth.S1_0_2URIAuth
- Data.URI.Auth.Host: instance Data.Data.Data Data.URI.Auth.Host.URIAuthHost
- Data.URI.Auth.Host: instance GHC.Generics.Constructor Data.URI.Auth.Host.C1_0URIAuthHost
- Data.URI.Auth.Host: instance GHC.Generics.Constructor Data.URI.Auth.Host.C1_1URIAuthHost
- Data.URI.Auth.Host: instance GHC.Generics.Constructor Data.URI.Auth.Host.C1_2URIAuthHost
- Data.URI.Auth.Host: instance GHC.Generics.Constructor Data.URI.Auth.Host.C1_3URIAuthHost
- Data.URI.Auth.Host: instance GHC.Generics.Datatype Data.URI.Auth.Host.D1URIAuthHost
- Data.URI.Auth.Host: instance GHC.Generics.Selector Data.URI.Auth.Host.S1_3_0URIAuthHost
- Data.URI.Auth.Host: instance GHC.Generics.Selector Data.URI.Auth.Host.S1_3_1URIAuthHost
- Data.URI.Auth.Host: parseIPv4 :: Parser IPv4
- Data.URI.Auth.Host: parseIPv6 :: Parser IPv6
- Data.URI.Auth.Host: showIPv4 :: IPv4 -> String
- Data.URI.Auth.Host: showIPv6 :: IPv6 -> String
- Data.URI.Auth.Host: type IPv4 = NTuple 4 Word8
- Data.URI.Auth.Host: type IPv6 = NTuple 8 Word16

Files

attoparsec-uri.cabal view
@@ -1,5 +1,5 @@ name:                attoparsec-uri-version:             0.0.1+version:             0.0.2 synopsis:            URI parser / printer using attoparsec -- description: homepage:            https://github.com/athanclark/attoparsec-uri#readme@@ -20,12 +20,14 @@                        Data.URI.Auth.Host   build-depends:       base >= 4.7 && < 5                      , attoparsec+                     , attoparsec-ip                      , bytedump-                     , n-tuple >= 0.0.1.1+                     , ip                      , strict                      , text                      , vector   default-language:    Haskell2010+  ghc-options:         -Wall  source-repository head   type:     git
src/Data/URI.hs view
@@ -10,23 +10,24 @@  import Data.URI.Auth (URIAuth, parseURIAuth) -import Prelude hiding (Maybe (..))+import Prelude hiding (Maybe (..), takeWhile)+import qualified Prelude as P import Data.Strict.Maybe (Maybe (..), fromMaybe) import Data.Strict.Tuple (Pair (..)) import Data.Text (Text) import qualified Data.Text as T import Data.Vector (Vector) import qualified Data.Vector as V-import Data.Attoparsec.Text (Parser, many1, notChar, char, string, sepBy, satisfy, anyChar)+import Data.Attoparsec.Text (Parser, char, string, sepBy, takeWhile, takeWhile1) import Data.List (intercalate)-import Control.Applicative ((<|>), many)+import Data.Char (isControl, isSpace)+import Control.Monad (void)+import Control.Applicative ((<|>), optional) -import Data.Data (Data, Typeable)+import Data.Data (Typeable) import GHC.Generics (Generic)  -deriving instance (Data a, Data b) => Data (Pair a b)- data URI = URI   { uriScheme    :: !(Maybe Text) -- ^ the scheme without the colon - @https://hackage.haskell.org/@ has a scheme of @https@   , uriSlashes   :: !Bool -- ^ are the slashes present? - @https://hackage.haskell.org/@ is @True@@@ -35,7 +36,7 @@   , uriQuery     :: !(Vector (Pair Text (Maybe Text))) -- ^ list of key-value pairs - @https://hackage.haskell.org/?foo=bar&baz&qux=@ is                                                        -- @[("foo", Just "bar"), ("baz", Nothing), ("qux", Just "")]@   , uriFragment  :: !(Maybe Text) -- ^ uri suffix - @https://hackage.haskell.org/#some-header@ is @Just "some-header"@-  } deriving (Eq, Data, Typeable, Generic)+  } deriving (Eq, Typeable, Generic)   instance Show URI where@@ -58,40 +59,45 @@  parseURI :: Parser URI parseURI =-  URI <$> ((Just <$> parseScheme) <|> pure Nothing)+  URI <$> (toStrictMaybe <$> optional parseScheme)       <*> parseSlashes       <*> parseURIAuth       <*> parsePath       <*> parseQuery-      <*> ((Just <$> parseFragment) <|> pure Nothing)+      <*> (toStrictMaybe <$> optional parseFragment)   where     parseScheme = do-      sch <- many1 (satisfy $ \c -> all (c /=) [':','/','@','.'])+      sch <- takeWhile1 (\c -> all (c /=) [':','/','@','.'])       _ <- char ':'-      pure (T.pack sch)+      pure sch     parseSlashes = do-      mS <- (Just <$> string "//") <|> pure Nothing+      mS <- optional (string "//")       case mS of-        Nothing -> pure False-        Just _  -> pure True+        P.Nothing -> pure False+        P.Just _  -> pure True     parsePath =-      ( do  _ <- char '/'-            V.fromList <$> (T.pack <$> many (satisfy $ \c -> all (c /=) ['/', '?', '=', '&', '#'])) `sepBy` (char '/')+      ( do  void $ char '/'+            V.fromList <$> parseChunkWithout ['/', '?', '=', '&', '#'] `sepBy` char '/'       ) <|> pure V.empty     parseQuery :: Parser (Vector (Pair Text (Maybe Text)))     parseQuery =-      ( do  _ <- char '?'+      ( do  void $ char '?'             let parse1 = do-                  k <- many (satisfy (\c -> all (c /=) ['=', '&', '#']))-                  mV <- ( Just <$> do _ <- char '='-                                      v <- many (satisfy $ \c -> c /= '&' && c /= '#')-                                      pure (T.pack v)+                  k <- parseChunkWithout ['=','&','#']+                  mV <- ( Just <$> do void $ char '='+                                      parseChunkWithout ['&','#']                         ) <|> ( pure Nothing                               )-                  pure (T.pack k :!: mV)-            qs <- parse1 `sepBy` (char '&')+                  pure (k :!: mV)+            qs <- parse1 `sepBy` char '&'             pure $ V.fromList qs       ) <|> pure V.empty     parseFragment = do-      _ <- char '#'-      T.pack <$> many anyChar+      void $ char '#'+      parseChunkWithout []+    parseChunkWithout :: [Char] -> Parser Text+    parseChunkWithout xs =+      takeWhile (\c -> not (isControl c || isSpace c) && all (c /=) xs)++    toStrictMaybe P.Nothing = Nothing+    toStrictMaybe (P.Just x) = Just x
src/Data/URI/Auth.hs view
@@ -11,26 +11,25 @@ import Data.URI.Auth.Host (URIAuthHost, parseURIAuthHost)  import Prelude hiding (Maybe (..))+import qualified Prelude as P import Data.Strict.Maybe (Maybe (..), fromMaybe) import Data.Text (Text) import Data.Word (Word16) import qualified Data.Text as T-import Data.Attoparsec.Text (Parser, many1, char, notChar, satisfy, decimal, peekChar)+import Data.Attoparsec.Text (Parser, char, decimal, peekChar, takeWhile1) import Data.Monoid ((<>))-import Control.Applicative ((<|>))-import qualified GHC.Base+import Control.Monad (void)+import Control.Applicative (optional) -import Data.Data (Data, Typeable)+import Data.Data (Typeable) import GHC.Generics (Generic)  -deriving instance Data a => Data (Maybe a)- data URIAuth = URIAuth   { uriAuthUser :: !(Maybe Text) -- ^ a designated user - @ssh://git\@github.com@ is @git@   , uriAuthHost :: !URIAuthHost   , uriAuthPort :: !(Maybe Word16) -- ^ the port, if it exists - @foobar.com:3000@ is @3000@ as a 16-bit unsigned int.-  } deriving (Eq, Data, Typeable, Generic)+  } deriving (Eq, Typeable, Generic)  instance Show URIAuth where   show URIAuth{..} =@@ -41,18 +40,21 @@  parseURIAuth :: Parser URIAuth parseURIAuth =-  URIAuth <$> ((Just <$> parseUser) <|> pure Nothing)+  URIAuth <$> (toStrictMaybe <$> optional parseUser)           <*> parseURIAuthHost-          <*> ((Just <$> parsePort) <|> pure Nothing)+          <*> (toStrictMaybe <$> optional parsePort)   where     parseUser = do-      u <- many1 $ satisfy $ \c -> all (c /=) ['@','.',':','/','?','&','=']+      u <- takeWhile1 (\c -> all (c /=) ['@','.',':','/','?','&','='])       mC <- peekChar       case mC of-        GHC.Base.Nothing -> fail "no user @ thing"+        P.Nothing -> fail "no user @ thing"         _ -> do-          _ <- char '@'-          pure $ T.pack u+          void $ char '@'+          pure u     parsePort = do-      _ <- char ':'+      void $ char ':'       decimal++    toStrictMaybe P.Nothing = Nothing+    toStrictMaybe (P.Just x) = Just x
src/Data/URI/Auth/Host.hs view
@@ -2,120 +2,31 @@     DataKinds   , DeriveGeneric   , DeriveDataTypeable+  , OverloadedStrings   #-}  module Data.URI.Auth.Host where  import Prelude hiding (Either (..)) -import Data.Strict (Either (..)) import Data.Vector (Vector) import qualified Data.Vector as V-import Data.Text (Text)+import Data.Text (Text, unpack) import qualified Data.Text as T-import Data.NTuple (NTuple, _1, _2, _3, _4, _5, _6, _7, _8)-import qualified Data.NTuple as NTuple-import Data.Word (Word8, Word16)-import Data.Attoparsec.Text (Parser, peekChar', decimal, hexadecimal, char, notChar, sepBy1, many1, satisfy)-import Data.Char (isDigit, isHexDigit)-import Data.Bits ((.&.), shiftR)+import Data.Attoparsec.Text (Parser, char, sepBy1, takeWhile1)+import Data.Attoparsec.IP (ipv4, ipv6) import Data.List (intercalate) import Control.Applicative ((<|>))-import Text.Read (readMaybe)-import Text.Bytedump (hexString)+import Net.Types (IPv4, IPv6)+import qualified Net.IPv4.Text as IPv4+import qualified Net.IPv6.Text as IPv6 -import Data.Data (Data, Typeable)+import Data.Data (Typeable) import GHC.Generics (Generic)    -type IPv4 = NTuple 4 Word8--parseIPv4 :: Parser IPv4-parseIPv4 = do-  a <- parseOctet-  _ <- char '.'-  b <- parseOctet-  _ <- char '.'-  c <- parseOctet-  _ <- char '.'-  d <- parseOctet-  pure $ NTuple.incl _4 d-       . NTuple.incl _3 c-       . NTuple.incl _2 b-       . NTuple.incl _1 a-       $ NTuple.empty-  where-    parseOctet :: Parser Word8-    parseOctet = decimal--showIPv4 :: IPv4 -> String-showIPv4 xs =-  intercalate "." $ V.toList $ show <$> NTuple.toVector xs---type IPv6 = NTuple 8 Word16--parseIPv6 :: Parser IPv6-parseIPv6 = do-  a <- parseDiOctet-  _ <- char ':'-  b <- parseDiOctet-  _ <- char ':'-  c <- parseDiOctet-  _ <- char ':'-  d <- parseDiOctet-  _ <- char ':'-  let soFar = NTuple.incl _4 d-            . NTuple.incl _3 c-            . NTuple.incl _2 b-            . NTuple.incl _1 a-            $ NTuple.empty-  q <- peekChar'-  if q == ':'-    then pure $ NTuple.incl _8 0-              . NTuple.incl _7 0-              . NTuple.incl _6 0-              . NTuple.incl _5 0-              $ soFar-    else do-      e <- parseDiOctet-      _ <- char ':'-      f <- parseDiOctet-      _ <- char ':'-      g <- parseDiOctet-      _ <- char ':'-      h <- parseDiOctet-      pure $ NTuple.incl _8 h-           . NTuple.incl _7 g-           . NTuple.incl _6 f-           . NTuple.incl _5 e-           $ soFar-  where-    parseDiOctet :: Parser Word16-    parseDiOctet = hexadecimal---showIPv6 :: IPv6 -> String-showIPv6 xs =-  let xs'@(a:b:c:d:qs) = V.toList $ NTuple.toVector xs-  in  if all (== 0) qs-        then intercalate ":" (showWord16 <$> [a,b,c,d]) ++ "::"-        else intercalate ":" (showWord16 <$> xs')-  where-    showWord16 :: Word16 -> String-    showWord16 x =-      let (l,r) = breakWord16 x-      in  hexString l ++ hexString r-      where-        breakWord16 :: Word16 -> (Word8, Word8)-        breakWord16 x = ( fromIntegral $ (x .&. 0xFF00) `shiftR` 8-                        , fromIntegral $ x .&. 0xFF-                        )--- data URIAuthHost   = IPv4 !IPv4   | IPv6 !IPv6@@ -124,33 +35,33 @@     Host       { uriAuthHostName   :: !(Vector Text)       , uriAuthHostSuffix :: !Text-      } deriving (Eq, Data, Typeable, Generic)+      } deriving (Eq, Typeable, Generic)  instance Show URIAuthHost where-  show (IPv4 l4) = showIPv4 l4-  show (IPv6 r6) = showIPv6 r6+  show (IPv4 l4) = unpack (IPv4.encode l4)+  show (IPv6 r6) = unpack (IPv6.encode r6)   show Localhost = "localhost"   show (Host ns c) = intercalate "." $ V.toList $ T.unpack <$> ns `V.snoc` c   parseURIAuthHost :: Parser URIAuthHost parseURIAuthHost =-      (IPv4 <$> parseIPv4)-  <|> (IPv6 <$> parseIPv6)+      (IPv4 <$> ipv4)+  <|> (IPv6 <$> ipv6)   <|> parseHost   where     parseHost :: Parser URIAuthHost     parseHost = do-      xss@(x:xs) <- many1 (satisfy $ \c -> all (c /=) ['.',':','/','?']) `sepBy1` char '.'+      xss@(x:xs) <- takeWhile1 (\c -> all (c /=) ['.',':','/','?']) `sepBy1` char '.'       if null xs         then if x == "localhost"              then pure Localhost-             else fail "Only one term parsed"+             else fail $ "Only one term parsed: " ++ show xss         else let xss' :: Vector Text-                 xss' = T.pack <$> V.fromList xss+                 xss' = V.fromList xss                  unsnoc :: Vector a -> (Vector a, a)                  unsnoc x =                    let (fs,l) = V.splitAt (V.length x - 1) x                    in  (fs, l V.! 0)                  (ns,c) = unsnoc xss'-             in  pure (uncurry Host $ unsnoc xss')+             in  pure (Host ns c)