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 +20/−0
- Network/IP/Quoter.hs +49/−0
- Setup.hs +2/−0
- ip-quoter.cabal +33/−0
- test/test.hs +10/−0
+ 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