hw-ip 2.3.4.2 → 2.4.0.1
raw patch · 8 files changed
+109/−36 lines, 8 files
Files
- app/App/Commands.hs +2/−0
- app/App/Commands/RangeStats.hs +39/−0
- app/App/Commands/Types.hs +8/−0
- gen/HaskellWorks/Data/Network/Gen.hs +31/−0
- hw-ip.cabal +14/−5
- src/HaskellWorks/Data/Network/Ip/Ipv4.hs +8/−0
- test/HaskellWorks/Data/Network/Gen.hs +0/−31
- test/HaskellWorks/Data/Network/Ipv4Spec.hs +7/−0
app/App/Commands.hs view
@@ -1,5 +1,6 @@ module App.Commands where +import App.Commands.RangeStats import App.Commands.TextToWord import Data.Semigroup ((<>)) import Options.Applicative@@ -11,3 +12,4 @@ commandsGeneral = subparser $ mempty <> commandGroup "Commands:" <> cmdTextToWord+ <> cmdRangeStats
+ app/App/Commands/RangeStats.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++module App.Commands.RangeStats+ ( cmdRangeStats+ ) where++import Control.Lens+import Data.Generics.Product.Any+import Data.Semigroup ((<>))+import Options.Applicative hiding (columns)++import qualified App.Commands.Types as Z+import qualified HaskellWorks.Data.Network.Ip.Ipv4 as IPv4+import qualified HaskellWorks.Data.Network.Ip.Range as R+import qualified Text.Appar.String as AP++{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}+{-# ANN module ("HLint: ignore Redundant do" :: String) #-}++runRangeStats :: Z.RangeStatsOptions -> IO ()+runRangeStats opts =+ print $ length . R.rangeToList $ opts ^. the @"range"++optsRangeStats :: Parser Z.RangeStatsOptions+optsRangeStats = Z.RangeStatsOptions+ <$> option (maybeReader parseRange)+ ( long "range"+ <> short 'r'+ <> help "IP Range"+ <> metavar "RANGE"+ )++parseRange :: String -> Maybe (R.Range IPv4.IpAddress)+parseRange = AP.parse (R.parseRange IPv4.parseIpAddress)++cmdRangeStats :: Mod CommandFields (IO ())+cmdRangeStats = command "range-stats" $ flip info idm $ runRangeStats <$> optsRangeStats
app/App/Commands/Types.hs view
@@ -3,11 +3,19 @@ module App.Commands.Types ( TextToWordOptions(..)+ , RangeStatsOptions(..) ) where import GHC.Generics +import qualified HaskellWorks.Data.Network.Ip.Ipv4 as IPv4+import qualified HaskellWorks.Data.Network.Ip.Range as R+ data TextToWordOptions = TextToWordOptions { input :: FilePath , output :: FilePath+ } deriving (Eq, Show, Generic)++data RangeStatsOptions = RangeStatsOptions+ { range :: R.Range IPv4.IpAddress } deriving (Eq, Show, Generic)
+ gen/HaskellWorks/Data/Network/Gen.hs view
@@ -0,0 +1,31 @@+module HaskellWorks.Data.Network.Gen+ ( canonicalIpv4Block+ , canonicalIpv6Block+ ) where++import HaskellWorks.Data.Bits.BitWise+import HaskellWorks.Data.Network.Ip.Validity+import Hedgehog++import qualified Data.Bits as B+import qualified HaskellWorks.Data.Network.Ip.Ipv4 as V4+import qualified HaskellWorks.Data.Network.Ip.Ipv6 as V6+import qualified Hedgehog.Gen as G+import qualified Hedgehog.Range as R++canonicalIpv4Block :: MonadGen m => m (V4.IpBlock Canonical)+canonicalIpv4Block = do+ m <- G.word8 (R.linear 0 32)+ let p = fromIntegral (32 - m)+ w <- G.word32 (R.linear 0 ((0xffffffff .>. p) .<. p))+ return (V4.IpBlock (V4.IpAddress (w .<. p)) (V4.IpNetMask m))++canonicalIpv6Block :: MonadGen m => m (V6.IpBlock Canonical)+canonicalIpv6Block = do+ m <- G.word8 (R.linear 0 128)+ let p = fromIntegral (128 - m)+ w128 <- (,,,) <$> G.word32 (R.linear 0 0xffffffff)+ <*> G.word32 (R.linear 0 0xffffffff)+ <*> G.word32 (R.linear 0 0xffffffff)+ <*> G.word32 (R.linear 0 0xffffffff)+ return (V6.IpBlock (V6.IpAddress (w128 `B.shift` p)) (V6.IpNetMask m))
hw-ip.cabal view
@@ -1,7 +1,7 @@-cabal-version: 2.2+cabal-version: 2.4 name: hw-ip-version: 2.3.4.2+version: 2.4.0.1 license: BSD-3-Clause license-file: LICENSE copyright: 2018-2019 John Ky, David Turnbull, Jian Wan@@ -76,6 +76,7 @@ , semigroups , text other-modules: App.Commands+ App.Commands.RangeStats App.Commands.TextToWord App.Commands.Types main-is: Main.hs@@ -83,6 +84,15 @@ ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends: hw-ip +library hw-ip-gen+ import: base, config+ , hedgehog+ , hw-bits+ , text+ exposed-modules: HaskellWorks.Data.Network.Gen+ hs-source-dirs: gen+ build-depends: hw-ip+ test-suite hw-ip-test import: base, config , appar@@ -92,8 +102,7 @@ , hw-bits , hw-hspec-hedgehog , text- other-modules: HaskellWorks.Data.Network.Gen- HaskellWorks.Data.Network.IpBlockSpec+ other-modules: HaskellWorks.Data.Network.IpBlockSpec HaskellWorks.Data.Network.IpSpec HaskellWorks.Data.Network.Ipv4Spec HaskellWorks.Data.Network.Ipv6Spec@@ -103,5 +112,5 @@ main-is: Spec.hs hs-source-dirs: test ghc-options: -threaded -rtsopts -with-rtsopts=-N- build-depends: hw-ip+ build-depends: hw-ip, hw-ip-gen build-tool-depends: hspec-discover:hspec-discover
src/HaskellWorks/Data/Network/Ip/Ipv4.hs view
@@ -19,6 +19,7 @@ , showsIpAddress , tshowIpAddress , tshowIpBlock+ , wordsToIpAddress , ipAddressToWords , firstIpAddress , lastIpAddress@@ -135,6 +136,13 @@ tshowIpBlock :: IpBlock v -> T.Text tshowIpBlock = T.pack . showIpBlock++wordsToIpAddress :: Word8 -> Word8 -> Word8 -> Word8 -> IpAddress+wordsToIpAddress a b c d = IpAddress $+ ( fromIntegral a .<. 24) .|.+ ( fromIntegral b .<. 16) .|.+ ( fromIntegral c .<. 8) .|.+ fromIntegral d ipAddressToWords :: IpAddress -> (Word8, Word8, Word8, Word8) ipAddressToWords (IpAddress w) =
− test/HaskellWorks/Data/Network/Gen.hs
@@ -1,31 +0,0 @@-module HaskellWorks.Data.Network.Gen- ( canonicalIpv4Block- , canonicalIpv6Block- ) where--import HaskellWorks.Data.Bits.BitWise-import HaskellWorks.Data.Network.Ip.Validity-import Hedgehog--import qualified Data.Bits as B-import qualified HaskellWorks.Data.Network.Ip.Ipv4 as V4-import qualified HaskellWorks.Data.Network.Ip.Ipv6 as V6-import qualified Hedgehog.Gen as G-import qualified Hedgehog.Range as R--canonicalIpv4Block :: MonadGen m => m (V4.IpBlock Canonical)-canonicalIpv4Block = do- m <- G.word8 (R.linear 0 32)- let p = fromIntegral (32 - m)- w <- G.word32 (R.linear 0 ((0xffffffff .>. p) .<. p))- return (V4.IpBlock (V4.IpAddress (w .<. p)) (V4.IpNetMask m))--canonicalIpv6Block :: MonadGen m => m (V6.IpBlock Canonical)-canonicalIpv6Block = do- m <- G.word8 (R.linear 0 128)- let p = fromIntegral (128 - m)- w128 <- (,,,) <$> G.word32 (R.linear 0 0xffffffff)- <*> G.word32 (R.linear 0 0xffffffff)- <*> G.word32 (R.linear 0 0xffffffff)- <*> G.word32 (R.linear 0 0xffffffff)- return (V6.IpBlock (V6.IpAddress (w128 `B.shift` p)) (V6.IpNetMask m))
test/HaskellWorks/Data/Network/Ipv4Spec.hs view
@@ -102,6 +102,13 @@ let ipblocks3 = read @(IpBlock Canonical) <$> ["1.2.3.3/32", "1.2.3.0/32", "1.2.3.1/32", "1.2.3.2/32", "5.5.5.5/32"] collapseIpBlocks (DL.sort ipblocks3) === (read @(IpBlock Canonical) <$> ["1.2.3.0/30", "5.5.5.5/32"]) + it "words and ip should round trip" $ requireTest $ do+ a <- forAll $ G.word8 R.constantBounded+ b <- forAll $ G.word8 R.constantBounded+ c <- forAll $ G.word8 R.constantBounded+ d <- forAll $ G.word8 R.constantBounded+ ipAddressToWords (wordsToIpAddress a b c d) === (a, b, c, d)+ describe "should split ranges" $ do it "0.0.0.0 - 0.0.0.0" $ requireTest $ do let ip1 = read "0.0.0.0" :: I.IpAddress