packages feed

ip-quoter (empty) → 1.0.0.0

raw patch · 5 files changed

+114/−0 lines, 5 filesdep +basedep +ip-quoterdep +networksetup-changed

Dependencies added: base, ip-quoter, network, split, tasty, tasty-hunit, template-haskell

Files

+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2015 Shea Levy++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Network/IP/Quoter.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE TemplateHaskell #-}+module Network.IP.Quoter (ip) where++import Data.Char ( isDigit )+import Data.Bits ( (.|.), unsafeShiftL )+import Data.List.Split ( splitOn )+import Network.Socket ( HostAddress )+import Language.Haskell.TH.Quote ( QuasiQuoter( .. ) )+import Language.Haskell.TH.Syntax ( Q, Exp( .. ), Lit( .. ), Type ( .. ) )++-- | QuasiQuoter for ip addresses (e.g. '[ip|127.0.0.1|]')+ip :: QuasiQuoter+ip = QuasiQuoter+  { quotePat = \_ -> fail "Can't invoke the ip quasiquoter in a pattern context"+  , quoteType = \_ -> fail "Can't invoke the ip quasiquoter in a type context"+  , quoteDec = \_ ->+               fail "Can't invoke the ip quasiquoter in a declaration context"+  , quoteExp = parseIP+  }++parseDigit :: Char -> Q Integer+parseDigit c+  | isDigit c = return . fromIntegral $ (fromEnum c - fromEnum '0')+  | otherwise = fail "Non-digit in IP address"++parseSegment' :: String -> Integer -> Q Integer+parseSegment' [] total = return total+parseSegment' (digit : rest) total+  | total <= 25 = do+      next <- parseDigit digit+      if (total == 0) && (next == 0) && (not (null rest))+        then fail "Leading zero in IP address segment"+        else parseSegment' rest (total * 10 + next)+  | otherwise = fail "IP address segment too big"++parseSegment :: String -> Q Integer+parseSegment [] = fail "Empty IP address segment"+parseSegment str = parseSegment' str 0++parseIP :: String -> Q Exp+parseIP s = case (splitOn "." s) of+  l@[ first, second, third, fourth ] -> do+      bytes <- mapM (fmap (LitE . IntegerL) . parseSegment) l+      return $ SigE (foldl1 shiftAndOr bytes) (ConT ''HostAddress)+    where+      shiftAndOr acc exp = AppE (AppE (VarE '(.|.)) shifted) exp+        where+          shifted = AppE (AppE (VarE 'unsafeShiftL) acc) (LitE $ IntegerL 8)+  _ -> fail "IP address doesn't contain four segments"
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ ip-quoter.cabal view
@@ -0,0 +1,33 @@+name:                ip-quoter+version:             1.0.0.0+synopsis:            Quasiquoter for IP addresses+description:+  A quasiquoter for IP address literals – That is, IPv4 decimal-dotted or IPv6+  colon-separated notation.++  Currently only IPv4 addresses are implemented.+homepage:            https://github.com/shlevy/ip-quoter+license:             MIT+license-file:        LICENSE+author:              Shea Levy+maintainer:          shea@shealevy.com+copyright:           (c) 2015 Shea Levy+category:            Network+build-type:          Simple+cabal-version:       >=1.10++library+  exposed-modules:   Network.IP.Quoter+  build-depends:     base >=4.8 && <5, template-haskell, split, network+  default-language:  Haskell2010++test-suite test+  type:              exitcode-stdio-1.0+  hs-source-dirs:    test+  main-is:           test.hs+  build-depends:     base >=4.8 && <5, tasty, tasty-hunit, network, ip-quoter+  default-language:  Haskell2010++source-repository head+  type:              git+  location:          git://github.com/shlevy/ip-quoter.git
+ test/test.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE QuasiQuotes #-}+import Test.Tasty+import Test.Tasty.HUnit+import Network.Socket+import Network.IP.Quoter++main = defaultMain tests++tests :: TestTree+tests = testCase "INADDR_ANY" $ [ip|0.0.0.0|] @=? iNADDR_ANY