packages feed

hw-ip 0.4.2 → 1.0.0.0

raw patch · 9 files changed

+410/−214 lines, 9 filesdep +appardep +iproutedep ~attoparsecdep ~basedep ~generic-lensPVP ok

version bump matches the API change (PVP)

Dependencies added: appar, iproute

Dependency ranges changed: attoparsec, base, generic-lens, hedgehog, hspec, hw-bits, hw-hspec-hedgehog, text

API changes (from Hackage documentation)

- HaskellWorks.Data.Network.Ip: Ipv4Address :: Word32 -> Ipv4Address
- HaskellWorks.Data.Network.Ip: Ipv4Block :: !Ipv4Address -> !Ipv4NetMask -> Ipv4Block
- HaskellWorks.Data.Network.Ip: Ipv4NetMask :: Word8 -> Ipv4NetMask
- HaskellWorks.Data.Network.Ip: bitPower :: Ipv4NetMask -> Word64
- HaskellWorks.Data.Network.Ip: blockSize :: Ipv4Block -> Int
- HaskellWorks.Data.Network.Ip: data Ipv4Block
- HaskellWorks.Data.Network.Ip: firstIpv4Address :: Ipv4Block -> Ipv4Address
- HaskellWorks.Data.Network.Ip: ipv4AddressToString :: Ipv4Address -> String
- HaskellWorks.Data.Network.Ip: ipv4AddressToText :: Ipv4Address -> Text
- HaskellWorks.Data.Network.Ip: ipv4AddressToWords :: Ipv4Address -> (Word8, Word8, Word8, Word8)
- HaskellWorks.Data.Network.Ip: isCanonical :: Ipv4Block -> Bool
- HaskellWorks.Data.Network.Ip: lastIpv4Address :: Ipv4Block -> Ipv4Address
- HaskellWorks.Data.Network.Ip: newtype Ipv4Address
- HaskellWorks.Data.Network.Ip: newtype Ipv4NetMask
- HaskellWorks.Data.Network.Ip: splitBlock :: Ipv4Block -> Maybe (Ipv4Block, Ipv4Block)
- HaskellWorks.Data.Network.Ip: textToMaybeIpv4Address :: Text -> Maybe Ipv4Address
- HaskellWorks.Data.Network.Ip.Parser.Text: ipv4Address :: Parser Ipv4Address
- HaskellWorks.Data.Network.Ip.Type: [$sel:word:Ipv4NetMask] :: Ipv4NetMask -> Word8
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Classes.Eq HaskellWorks.Data.Network.Ip.Type.Ipv4Address
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Classes.Eq HaskellWorks.Data.Network.Ip.Type.Ipv4Block
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Classes.Eq HaskellWorks.Data.Network.Ip.Type.Ipv4NetMask
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Classes.Ord HaskellWorks.Data.Network.Ip.Type.Ipv4Address
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Classes.Ord HaskellWorks.Data.Network.Ip.Type.Ipv4Block
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Classes.Ord HaskellWorks.Data.Network.Ip.Type.Ipv4NetMask
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Enum.Enum HaskellWorks.Data.Network.Ip.Type.Ipv4Address
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Enum.Enum HaskellWorks.Data.Network.Ip.Type.Ipv4NetMask
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Generics.Generic HaskellWorks.Data.Network.Ip.Type.Ipv4Address
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Generics.Generic HaskellWorks.Data.Network.Ip.Type.Ipv4NetMask
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Read.Read HaskellWorks.Data.Network.Ip.Type.Ipv4Address
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Read.Read HaskellWorks.Data.Network.Ip.Type.Ipv4Block
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Show.Show HaskellWorks.Data.Network.Ip.Type.Ipv4Address
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Show.Show HaskellWorks.Data.Network.Ip.Type.Ipv4Block
- HaskellWorks.Data.Network.Ip.Type: instance GHC.Show.Show HaskellWorks.Data.Network.Ip.Type.Ipv4NetMask
+ HaskellWorks.Data.Network.Ip.Internal: word32x4ToWords :: (Word32, Word32, Word32, Word32) -> [Word32]
+ HaskellWorks.Data.Network.Ip.Ip: IpBlockV4 :: Ipv4Block -> IpBlock
+ HaskellWorks.Data.Network.Ip.Ip: IpBlockV6 :: Ipv6Block -> IpBlock
+ HaskellWorks.Data.Network.Ip.Ip: data IpBlock
+ HaskellWorks.Data.Network.Ip.Ip: firstAddress :: IpBlock -> (Word32, Word32, Word32, Word32)
+ HaskellWorks.Data.Network.Ip.Ip: instance GHC.Classes.Eq HaskellWorks.Data.Network.Ip.Ip.IpBlock
+ HaskellWorks.Data.Network.Ip.Ip: instance GHC.Classes.Ord HaskellWorks.Data.Network.Ip.Ip.IpBlock
+ HaskellWorks.Data.Network.Ip.Ip: instance GHC.Generics.Generic HaskellWorks.Data.Network.Ip.Ip.IpBlock
+ HaskellWorks.Data.Network.Ip.Ip: instance GHC.Read.Read HaskellWorks.Data.Network.Ip.Ip.IpBlock
+ HaskellWorks.Data.Network.Ip.Ip: instance GHC.Show.Show HaskellWorks.Data.Network.Ip.Ip.IpBlock
+ HaskellWorks.Data.Network.Ip.Ip: isValidIpBlock :: IpBlock -> Bool
+ HaskellWorks.Data.Network.Ip.Ip: lastAddress :: IpBlock -> (Word32, Word32, Word32, Word32)
+ HaskellWorks.Data.Network.Ip.Ipv4: Ipv4Address :: Word32 -> Ipv4Address
+ HaskellWorks.Data.Network.Ip.Ipv4: Ipv4Block :: !Ipv4Address -> !Ipv4NetMask -> Ipv4Block
+ HaskellWorks.Data.Network.Ip.Ipv4: Ipv4NetMask :: Word8 -> Ipv4NetMask
+ HaskellWorks.Data.Network.Ip.Ipv4: [$sel:base:Ipv4Block] :: Ipv4Block -> !Ipv4Address
+ HaskellWorks.Data.Network.Ip.Ipv4: [$sel:mask:Ipv4Block] :: Ipv4Block -> !Ipv4NetMask
+ HaskellWorks.Data.Network.Ip.Ipv4: [$sel:word8:Ipv4NetMask] :: Ipv4NetMask -> Word8
+ HaskellWorks.Data.Network.Ip.Ipv4: [$sel:word:Ipv4Address] :: Ipv4Address -> Word32
+ HaskellWorks.Data.Network.Ip.Ipv4: bitPower :: Ipv4NetMask -> Word64
+ HaskellWorks.Data.Network.Ip.Ipv4: blockSize :: Ipv4Block -> Int
+ HaskellWorks.Data.Network.Ip.Ipv4: data Ipv4Block
+ HaskellWorks.Data.Network.Ip.Ipv4: firstIpv4Address :: Ipv4Block -> Ipv4Address
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Classes.Eq HaskellWorks.Data.Network.Ip.Ipv4.Ipv4Address
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Classes.Eq HaskellWorks.Data.Network.Ip.Ipv4.Ipv4Block
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Classes.Eq HaskellWorks.Data.Network.Ip.Ipv4.Ipv4NetMask
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Classes.Ord HaskellWorks.Data.Network.Ip.Ipv4.Ipv4Address
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Classes.Ord HaskellWorks.Data.Network.Ip.Ipv4.Ipv4Block
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Classes.Ord HaskellWorks.Data.Network.Ip.Ipv4.Ipv4NetMask
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Enum.Enum HaskellWorks.Data.Network.Ip.Ipv4.Ipv4Address
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Enum.Enum HaskellWorks.Data.Network.Ip.Ipv4.Ipv4NetMask
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Generics.Generic HaskellWorks.Data.Network.Ip.Ipv4.Ipv4Address
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Generics.Generic HaskellWorks.Data.Network.Ip.Ipv4.Ipv4NetMask
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Read.Read HaskellWorks.Data.Network.Ip.Ipv4.Ipv4Address
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Read.Read HaskellWorks.Data.Network.Ip.Ipv4.Ipv4Block
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Show.Show HaskellWorks.Data.Network.Ip.Ipv4.Ipv4Address
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Show.Show HaskellWorks.Data.Network.Ip.Ipv4.Ipv4Block
+ HaskellWorks.Data.Network.Ip.Ipv4: instance GHC.Show.Show HaskellWorks.Data.Network.Ip.Ipv4.Ipv4NetMask
+ HaskellWorks.Data.Network.Ip.Ipv4: ipv4AddressToString :: Ipv4Address -> String
+ HaskellWorks.Data.Network.Ip.Ipv4: ipv4AddressToText :: Ipv4Address -> Text
+ HaskellWorks.Data.Network.Ip.Ipv4: ipv4AddressToWords :: Ipv4Address -> (Word8, Word8, Word8, Word8)
+ HaskellWorks.Data.Network.Ip.Ipv4: isCanonical :: Ipv4Block -> Bool
+ HaskellWorks.Data.Network.Ip.Ipv4: isValidIpv4Block :: Ipv4Block -> Bool
+ HaskellWorks.Data.Network.Ip.Ipv4: lastIpv4Address :: Ipv4Block -> Ipv4Address
+ HaskellWorks.Data.Network.Ip.Ipv4: newtype Ipv4Address
+ HaskellWorks.Data.Network.Ip.Ipv4: newtype Ipv4NetMask
+ HaskellWorks.Data.Network.Ip.Ipv4: parseIpv4Address :: Parser Ipv4Address
+ HaskellWorks.Data.Network.Ip.Ipv4: splitBlock :: Ipv4Block -> Maybe (Ipv4Block, Ipv4Block)
+ HaskellWorks.Data.Network.Ip.Ipv4: textToMaybeIpv4Address :: Text -> Maybe Ipv4Address
+ HaskellWorks.Data.Network.Ip.Ipv6: Ipv6Address :: (Word32, Word32, Word32, Word32) -> Ipv6Address
+ HaskellWorks.Data.Network.Ip.Ipv6: Ipv6Block :: !Ipv6Address -> !Ipv6NetMask -> Ipv6Block
+ HaskellWorks.Data.Network.Ip.Ipv6: Ipv6NetMask :: Word8 -> Ipv6NetMask
+ HaskellWorks.Data.Network.Ip.Ipv6: [$sel:base:Ipv6Block] :: Ipv6Block -> !Ipv6Address
+ HaskellWorks.Data.Network.Ip.Ipv6: [$sel:mask:Ipv6Block] :: Ipv6Block -> !Ipv6NetMask
+ HaskellWorks.Data.Network.Ip.Ipv6: [$sel:word:Ipv6NetMask] :: Ipv6NetMask -> Word8
+ HaskellWorks.Data.Network.Ip.Ipv6: [$sel:words:Ipv6Address] :: Ipv6Address -> (Word32, Word32, Word32, Word32)
+ HaskellWorks.Data.Network.Ip.Ipv6: data Ipv6Block
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Classes.Eq HaskellWorks.Data.Network.Ip.Ipv6.Ipv6Address
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Classes.Eq HaskellWorks.Data.Network.Ip.Ipv6.Ipv6Block
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Classes.Eq HaskellWorks.Data.Network.Ip.Ipv6.Ipv6NetMask
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Classes.Ord HaskellWorks.Data.Network.Ip.Ipv6.Ipv6Address
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Classes.Ord HaskellWorks.Data.Network.Ip.Ipv6.Ipv6Block
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Classes.Ord HaskellWorks.Data.Network.Ip.Ipv6.Ipv6NetMask
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Enum.Enum HaskellWorks.Data.Network.Ip.Ipv6.Ipv6NetMask
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Generics.Generic HaskellWorks.Data.Network.Ip.Ipv6.Ipv6Address
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Generics.Generic HaskellWorks.Data.Network.Ip.Ipv6.Ipv6Block
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Generics.Generic HaskellWorks.Data.Network.Ip.Ipv6.Ipv6NetMask
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Read.Read HaskellWorks.Data.Network.Ip.Ipv6.Ipv6Address
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Read.Read HaskellWorks.Data.Network.Ip.Ipv6.Ipv6Block
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Read.Read HaskellWorks.Data.Network.Ip.Ipv6.Ipv6NetMask
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Show.Show HaskellWorks.Data.Network.Ip.Ipv6.Ipv6Address
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Show.Show HaskellWorks.Data.Network.Ip.Ipv6.Ipv6Block
+ HaskellWorks.Data.Network.Ip.Ipv6: instance GHC.Show.Show HaskellWorks.Data.Network.Ip.Ipv6.Ipv6NetMask
+ HaskellWorks.Data.Network.Ip.Ipv6: ipv4BlockToMappedIpv6Block :: Ipv4Block -> Ipv6Block
+ HaskellWorks.Data.Network.Ip.Ipv6: isValidIpv6Block :: Ipv6Block -> Bool
+ HaskellWorks.Data.Network.Ip.Ipv6: masksIpv6 :: Word8 -> [Word32]
+ HaskellWorks.Data.Network.Ip.Ipv6: newtype Ipv6Address
+ HaskellWorks.Data.Network.Ip.Ipv6: newtype Ipv6NetMask
+ HaskellWorks.Data.Network.Ip.Ipv6: parseIpv6Block :: Text -> Either Text Ipv6Block
+ HaskellWorks.Data.Network.Ip.Type: Ipv6Address :: (Word32, Word32, Word32, Word32) -> Ipv6Address
+ HaskellWorks.Data.Network.Ip.Type: Ipv6Block :: !Ipv6Address -> !Ipv6NetMask -> Ipv6Block
+ HaskellWorks.Data.Network.Ip.Type: Ipv6NetMask :: Word8 -> Ipv6NetMask
+ HaskellWorks.Data.Network.Ip.Type: [$sel:base:Ipv6Block] :: Ipv6Block -> !Ipv6Address
+ HaskellWorks.Data.Network.Ip.Type: [$sel:mask:Ipv6Block] :: Ipv6Block -> !Ipv6NetMask
+ HaskellWorks.Data.Network.Ip.Type: [$sel:word8:Ipv4NetMask] :: Ipv4NetMask -> Word8
+ HaskellWorks.Data.Network.Ip.Type: [$sel:word:Ipv6NetMask] :: Ipv6NetMask -> Word8
+ HaskellWorks.Data.Network.Ip.Type: [$sel:words:Ipv6Address] :: Ipv6Address -> (Word32, Word32, Word32, Word32)
+ HaskellWorks.Data.Network.Ip.Type: data Ipv6Block
+ HaskellWorks.Data.Network.Ip.Type: newtype Ipv6Address
+ HaskellWorks.Data.Network.Ip.Type: newtype Ipv6NetMask

Files

hw-ip.cabal view
@@ -1,65 +1,64 @@--- This file has been generated from package.yaml by hpack version 0.18.1.------ see: https://github.com/sol/hpack--name:           hw-ip-version:        0.4.2-synopsis:       Library for manipulating IP addresses and CIDR blocks-description:    Please see README.md-category:       Network-homepage:       https://github.com/haskell-works/hw-ip#readme-bug-reports:    https://github.com/haskell-works/hw-ip/issues-author:         John Ky,-                David Turnbull,-                Jian Wan-maintainer:     newhoggy@gmail.com-copyright:      2018 John Ky-license:        BSD3-license-file:   LICENSE-build-type:     Simple-cabal-version:  >= 1.10-+cabal-version: 1.12+name: hw-ip+version: 1.0.0.0+license: BSD3+license-file: LICENSE+copyright: 2018 John Ky, David Turnbull, Jian Wan+maintainer: newhoggy@gmail.com+author: John Ky,+        David Turnbull,+        Jian Wan+homepage: https://github.com/haskell-works/hw-ip#readme+bug-reports: https://github.com/haskell-works/hw-ip/issues+synopsis: Library for manipulating IP addresses and CIDR blocks+description:+    Please see README.md+category: Network+build-type: Simple extra-source-files:     README.md  source-repository head-  type: git-  location: https://github.com/haskell-works/hw-ip+    type: git+    location: https://github.com/haskell-works/hw-ip  library-  hs-source-dirs:-      src-  build-depends:-      attoparsec-    , generic-lens-    , hw-bits-    , text-    , base >=4.7 && <5-  exposed-modules:+    exposed-modules:       HaskellWorks.Data.Network.Ip+      HaskellWorks.Data.Network.Ip.Ip+      HaskellWorks.Data.Network.Ip.Ipv6       HaskellWorks.Data.Network.Ip.Internal-      HaskellWorks.Data.Network.Ip.Parser.Text+      HaskellWorks.Data.Network.Ip.Ipv4       HaskellWorks.Data.Network.Ip.Type-  other-modules:-      Paths_hw_ip-  default-language: Haskell2010+    hs-source-dirs: src+    other-modules:+        Paths_hw_ip+    default-language: Haskell2010+    build-depends:+        base            >= 4            && < 4.13+      , appar           >= 0.1.7        && < 0.2+      , attoparsec      >= 0.13.2.2     && < 0.14+      , generic-lens    >= 0.5.1.0      && < 1.2+      , hw-bits         >= 0.7.0.2      && < 0.8+      , iproute         >= 1.7.3        && < 1.8+      , text            >= 1.2.2.2      && < 1.3  test-suite hw-ip-test-  type: exitcode-stdio-1.0-  main-is: Spec.hs-  hs-source-dirs:-      test-  ghc-options: -threaded -rtsopts -with-rtsopts=-N-  build-depends:-      attoparsec-    , generic-lens-    , hw-bits-    , text-    , base-    , hedgehog-    , hw-hspec-hedgehog-    , hw-ip-    , hspec-  other-modules:-      HaskellWorks.Data.Network.IpSpec-  default-language: Haskell2010+    type: exitcode-stdio-1.0+    main-is: Spec.hs+    hs-source-dirs: test+    other-modules:+        HaskellWorks.Data.Network.IpSpec+        Paths_hw_ip+    default-language: Haskell2010+    ghc-options: -threaded -rtsopts -with-rtsopts=-N+    build-depends:+        base              >= 4          && < 4.13+      , attoparsec+      , generic-lens+      , hedgehog          >= 0.5.3      && < 0.7+      , hspec             >= 2.4.4      && < 2.6+      , hw-bits+      , hw-hspec-hedgehog >= 0.1.0.2    && < 0.2+      , hw-ip+      , text
src/HaskellWorks/Data/Network/Ip.hs view
@@ -1,73 +1,9 @@-{-# LANGUAGE BangPatterns          #-}-{-# LANGUAGE DuplicateRecordFields #-}- module HaskellWorks.Data.Network.Ip-  ( Z.Ipv4Address(Ipv4Address)-  , Z.Ipv4NetMask(Ipv4NetMask)-  , Z.Ipv4Block(Ipv4Block)-  , bitPower-  , blockSize-  , isCanonical-  , splitBlock-  , textToMaybeIpv4Address-  , ipv4AddressToString-  , ipv4AddressToText-  , ipv4AddressToWords-  , firstIpv4Address-  , lastIpv4Address+  ( module X   ) where -import Control.Monad-import Data.Word-import GHC.Generics-import HaskellWorks.Data.Bits.BitWise--import qualified Data.Attoparsec.Text                     as AP-import qualified Data.Text                                as T-import qualified HaskellWorks.Data.Network.Ip.Internal    as I-import qualified HaskellWorks.Data.Network.Ip.Parser.Text as APT-import qualified HaskellWorks.Data.Network.Ip.Type        as Z--bitPower :: Z.Ipv4NetMask -> Word64-bitPower (Z.Ipv4NetMask m) = fromIntegral (32 - m)--isCanonical :: Z.Ipv4Block -> Bool-isCanonical (Z.Ipv4Block (Z.Ipv4Address b) m) = ((b .>. bitPower m) .<. bitPower m) == b--splitBlock :: Z.Ipv4Block -> Maybe (Z.Ipv4Block, Z.Ipv4Block)-splitBlock (Z.Ipv4Block (Z.Ipv4Address b) (Z.Ipv4NetMask m)) =-  if m >= 0 && m < 32-    then  let !hm       = m + 1-              !halfMask = Z.Ipv4NetMask hm-              !c        = fromIntegral ((0x100000000 :: Word64) .>. fromIntegral (m + 1))-          in  Just-              ( Z.Ipv4Block (Z.Ipv4Address  b     ) halfMask-              , Z.Ipv4Block (Z.Ipv4Address (b + c)) halfMask-              )-    else  Nothing--blockSize :: Z.Ipv4Block -> Int-blockSize (Z.Ipv4Block _ m) = 2 ^ bitPower m--firstIpv4Address :: Z.Ipv4Block -> Z.Ipv4Address-firstIpv4Address (Z.Ipv4Block base _) = base--lastIpv4Address :: Z.Ipv4Block -> Z.Ipv4Address-lastIpv4Address b@(Z.Ipv4Block (Z.Ipv4Address base) _) = Z.Ipv4Address (base + fromIntegral (blockSize b) - 1)--textToMaybeIpv4Address :: T.Text -> Maybe Z.Ipv4Address-textToMaybeIpv4Address t = AP.maybeResult =<< AP.parseWith (return mempty) APT.ipv4Address t--ipv4AddressToString :: Z.Ipv4Address -> String-ipv4AddressToString = show--ipv4AddressToText :: Z.Ipv4Address -> T.Text-ipv4AddressToText = T.pack . ipv4AddressToString--ipv4AddressToWords :: Z.Ipv4Address -> (Word8, Word8, Word8, Word8)-ipv4AddressToWords (Z.Ipv4Address w) =-  ( fromIntegral (w .>. 24) .&. 0xff-  , fromIntegral (w .>. 16) .&. 0xff-  , fromIntegral (w .>.  8) .&. 0xff-  , fromIntegral (w         .&. 0xff)-  )+import HaskellWorks.Data.Network.Ip.Internal as X+import HaskellWorks.Data.Network.Ip.Ip       as X+import HaskellWorks.Data.Network.Ip.Ipv4     as X+import HaskellWorks.Data.Network.Ip.Ipv6     as X+import HaskellWorks.Data.Network.Ip.Type     as X
src/HaskellWorks/Data/Network/Ip/Internal.hs view
@@ -29,6 +29,9 @@   <|>    ds 1 9 #<*># ds 0 9   <|>    ds 0 9 +whitespace :: AP.Parser ()+whitespace = void $ many (AP.satisfy isSpace)+ ipv4Address :: AP.Parser Word32 ipv4Address = fourOctetsToWord32   <$> (octet <* AP.char '.')@@ -36,9 +39,6 @@   <*> (octet <* AP.char '.')   <*>  octet -whitespace :: AP.Parser ()-whitespace = void $ many (AP.satisfy isSpace)- ipv4NetMask :: AP.Parser Word8 ipv4NetMask =  d 3   #<*># ds 0 2   <|>          d 2   #<*># ds 0 9@@ -57,3 +57,6 @@   _    <- AP.char '/'   mask <- ipv4NetMask   return (addr, mask)++word32x4ToWords :: (Word32, Word32, Word32, Word32) -> [Word32]+word32x4ToWords (a, b, c, d) = [a, b, c, d]
+ src/HaskellWorks/Data/Network/Ip/Ip.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE DuplicateRecordFields      #-}+{-# LANGUAGE InstanceSigs               #-}+{-# LANGUAGE OverloadedStrings          #-}++module HaskellWorks.Data.Network.Ip.Ip+  ( IpBlock(..)+  , isValidIpBlock+  , firstAddress+  , lastAddress+  ) where++import Control.Applicative+import Control.Monad+import Data.Char+import Data.Maybe+import Data.Word+import GHC.Generics+import HaskellWorks.Data.Bits.BitWise+import Text.Read++import qualified Data.Attoparsec.Text                  as AP+import qualified Data.Bits                             as B+import qualified Data.Text                             as T+import qualified HaskellWorks.Data.Network.Ip.Internal as I+import qualified HaskellWorks.Data.Network.Ip.Ipv4     as I4+import qualified HaskellWorks.Data.Network.Ip.Ipv6     as I6+import qualified Text.ParserCombinators.ReadPrec       as RP++data IpBlock = IpBlockV4 I4.Ipv4Block | IpBlockV6 I6.Ipv6Block+  deriving (Eq, Ord, Generic)++instance Show IpBlock where+  showsPrec _ (IpBlockV4 a) = shows a+  showsPrec _ (IpBlockV6 a) = shows a++instance Read IpBlock where+  readsPrec _ s =+    case readMaybe s :: Maybe I4.Ipv4Block of+      Just ipv4 -> [(IpBlockV4 ipv4, "")]++      Nothing ->+        case readMaybe s :: Maybe I6.Ipv6Block of+          Just ipv6 -> [(IpBlockV6 ipv6, "")]+          Nothing   -> []++isValidIpBlock :: IpBlock -> Bool+isValidIpBlock (IpBlockV4 b) = I4.isValidIpv4Block b+isValidIpBlock (IpBlockV6 b) = I6.isValidIpv6Block b++firstAddress :: IpBlock -> (Word32, Word32, Word32, Word32)+firstAddress (IpBlockV4 i4b)                 = firstAddress (IpBlockV6 (I6.ipv4BlockToMappedIpv6Block i4b))+firstAddress (IpBlockV6 (I6.Ipv6Block ip _)) = I6.words ip++lastAddress :: IpBlock -> (Word32, Word32, Word32, Word32)+lastAddress (IpBlockV4 ib) = (0, 0, 0xFFFF, I4.word (I4.lastIpv4Address ib))+lastAddress (IpBlockV6 (I6.Ipv6Block ip (I6.Ipv6NetMask msk))) =+    let (w1, w2, w3, w4) = I6.words ip+        lt = I6.masksIpv6 $ fromIntegral msk+        w1' = w1 .|. (lt !! 0)+        w2' = w2 .|. (lt !! 1)+        w3' = w3 .|. (lt !! 2)+        w4' = w4 .|. (lt !! 3) in+      (w1', w2', w3', w4')
+ src/HaskellWorks/Data/Network/Ip/Ipv4.hs view
@@ -0,0 +1,140 @@+{-# LANGUAGE BangPatterns               #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE DuplicateRecordFields      #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE InstanceSigs               #-}++module HaskellWorks.Data.Network.Ip.Ipv4+  ( Ipv4Address(..)+  , Ipv4NetMask(..)+  , Ipv4Block(..)+  , isValidIpv4Block+  , bitPower+  , blockSize+  , isCanonical+  , splitBlock+  , textToMaybeIpv4Address+  , parseIpv4Address+  , ipv4AddressToString+  , ipv4AddressToText+  , ipv4AddressToWords+  , firstIpv4Address+  , lastIpv4Address+  ) where++import Control.Applicative+import Control.Monad+import Data.Char+import Data.Maybe+import Data.Word+import GHC.Generics+import HaskellWorks.Data.Bits.BitWise+import Text.Read++import qualified Data.Attoparsec.Text                  as AP+import qualified Data.Bits                             as B+import qualified Data.Text                             as T+import qualified HaskellWorks.Data.Network.Ip.Internal as I+import qualified Text.ParserCombinators.ReadPrec       as RP++newtype Ipv4Address = Ipv4Address+  { word :: Word32+  } deriving (Enum, Eq, Ord, Generic)++instance Show Ipv4Address where+  showsPrec _ (Ipv4Address w) =+    shows ((w .>. 24) .&. 0xff) . ('.':) .+    shows ((w .>. 16) .&. 0xff) . ('.':) .+    shows ((w .>.  8) .&. 0xff) . ('.':) .+    shows ( w         .&. 0xff)++instance Read Ipv4Address where+  readsPrec :: Int -> String -> [(Ipv4Address, String)]+  readsPrec _ s = case AP.parseWith (return mempty) (I.whitespace *> I.ipv4Address) (T.pack s) of+    Just result -> case result of+      AP.Done i r   -> [(Ipv4Address r, T.unpack i)]+      AP.Partial _  -> []+      AP.Fail a b c -> []+    Nothing -> []++newtype Ipv4NetMask = Ipv4NetMask+  { word8 :: Word8+  } deriving (Enum, Eq, Ord, Show, Generic)++data Ipv4Block = Ipv4Block+  { base :: !Ipv4Address+  , mask :: !Ipv4NetMask+  } deriving (Eq, Ord)++instance Show Ipv4Block where+  showsPrec _ (Ipv4Block b (Ipv4NetMask m)) = shows b . ('/':) . shows m++instance Read Ipv4Block where+  readsPrec :: Int -> String -> [(Ipv4Block, String)]+  readsPrec _ s = case AP.parseWith (return mempty) (I.whitespace *> I.ipv4Block) (T.pack s) of+    Just result -> case result of+      AP.Done i (a, m) ->+        case validIpv4Block $ Ipv4Block (Ipv4Address a) (Ipv4NetMask m) of+          Just b  -> [(b, T.unpack i)]+          Nothing -> []+      AP.Partial _    -> []+      AP.Fail a b c   -> []+    Nothing -> []++-- shift the address left by the amount of mask bits to reveal only host bits+-- if any bits left are non-zero, then the mask is not big enough+validIpv4Block :: Ipv4Block -> Maybe Ipv4Block+validIpv4Block b@(Ipv4Block (Ipv4Address word) (Ipv4NetMask mask)) =+  if word `B.shiftL` fromIntegral mask `B.xor` 0 == 0+    then pure b+    else Nothing++isValidIpv4Block :: Ipv4Block -> Bool+isValidIpv4Block = isJust . validIpv4Block++firstIpv4Address :: Ipv4Block -> Ipv4Address+firstIpv4Address (Ipv4Block base _) = base++lastIpv4Address :: Ipv4Block -> Ipv4Address+lastIpv4Address b@(Ipv4Block (Ipv4Address base) _) = Ipv4Address (base + fromIntegral (blockSize b) - 1)++bitPower :: Ipv4NetMask -> Word64+bitPower (Ipv4NetMask m) = fromIntegral (32 - m)++isCanonical :: Ipv4Block -> Bool+isCanonical (Ipv4Block (Ipv4Address b) m) = ((b .>. bitPower m) .<. bitPower m) == b++splitBlock :: Ipv4Block -> Maybe (Ipv4Block, Ipv4Block)+splitBlock (Ipv4Block (Ipv4Address b) (Ipv4NetMask m)) =+  if m >= 0 && m < 32+    then  let !hm       = m + 1+              !halfMask = Ipv4NetMask hm+              !c        = fromIntegral ((0x100000000 :: Word64) .>. fromIntegral (m + 1))+          in  Just+              ( Ipv4Block (Ipv4Address  b     ) halfMask+              , Ipv4Block (Ipv4Address (b + c)) halfMask+              )+    else  Nothing++blockSize :: Ipv4Block -> Int+blockSize (Ipv4Block _ m) = 2 ^ bitPower m++textToMaybeIpv4Address :: T.Text -> Maybe Ipv4Address+textToMaybeIpv4Address t = AP.maybeResult =<< AP.parseWith (return mempty) parseIpv4Address t++ipv4AddressToString :: Ipv4Address -> String+ipv4AddressToString = show++ipv4AddressToText :: Ipv4Address -> T.Text+ipv4AddressToText = T.pack . ipv4AddressToString++ipv4AddressToWords :: Ipv4Address -> (Word8, Word8, Word8, Word8)+ipv4AddressToWords (Ipv4Address w) =+  ( fromIntegral (w .>. 24) .&. 0xff+  , fromIntegral (w .>. 16) .&. 0xff+  , fromIntegral (w .>.  8) .&. 0xff+  , fromIntegral (w         .&. 0xff)+  )++parseIpv4Address :: AP.Parser Ipv4Address+parseIpv4Address = Ipv4Address <$> I.ipv4Address
+ src/HaskellWorks/Data/Network/Ip/Ipv6.hs view
@@ -0,0 +1,124 @@+{-# LANGUAGE DataKinds                  #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE DuplicateRecordFields      #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE InstanceSigs               #-}+{-# LANGUAGE OverloadedStrings          #-}+{-# LANGUAGE TypeApplications           #-}++module HaskellWorks.Data.Network.Ip.Ipv6+  ( Ipv6Address(..)+  , Ipv6NetMask(..)+  , Ipv6Block(..)+  , ipv4BlockToMappedIpv6Block+  , parseIpv6Block+  , masksIpv6+  , isValidIpv6Block+  ) where++import Control.Applicative+import Control.Monad+import Data.Bits+import Data.Char+import Data.Generics.Product.Any+import Data.Maybe+import Data.Word+import GHC.Generics+import Prelude                   hiding (words)+import Text.Read++import qualified Data.Attoparsec.Text                  as AP+import qualified Data.Bits                             as B+import qualified Data.IP                               as D+import qualified Data.String                           as S+import qualified Data.Text                             as T+import qualified HaskellWorks.Data.Network.Ip.Internal as I+import qualified HaskellWorks.Data.Network.Ip.Ipv4     as I4+import qualified Text.ParserCombinators.ReadPrec       as RP++newtype Ipv6Address = Ipv6Address+  { words :: (Word32, Word32, Word32, Word32)+  } deriving (Eq, Ord, Generic)++instance Show Ipv6Address where+  showsPrec _ (Ipv6Address w) = shows (D.fromHostAddress6 w)++instance Read Ipv6Address where+  readsPrec :: Int -> String -> [(Ipv6Address, String)]+  readsPrec _ s =+    case readMaybe s :: Maybe D.IPv6 of+      Just ip -> [(Ipv6Address (D.toHostAddress6 ip), "")]+      Nothing -> []++newtype Ipv6NetMask = Ipv6NetMask+  { word :: Word8+  } deriving (Enum, Eq, Ord, Show, Generic)++instance Read Ipv6NetMask where+  readsPrec _ s =+    case Ipv6NetMask <$> m of+      Just maskv6 -> [(maskv6, "")]+      Nothing     -> []+    where+      m = mfilter (\a -> a >= 0 && a <= 128) (readMaybe s)++data Ipv6Block = Ipv6Block+  { base :: !Ipv6Address+  , mask :: !Ipv6NetMask+  } deriving (Eq, Ord, Generic)++instance Read Ipv6Block where+  readsPrec _ s =+    case T.unpack <$> T.split (== '/') (T.pack s) of+      [addr, mask] ->+        case readMaybe addr :: Maybe Ipv6Address of+          Just ipv6 ->+            case readMaybe mask of+              Just maskv6 ->+                let i6b = Ipv6Block ipv6 maskv6 in+                  [(i6b, "") | isValidIpv6Block i6b]+              Nothing     -> []+          Nothing -> []+      _ -> []++instance Show Ipv6Block where+  showsPrec _ (Ipv6Block b (Ipv6NetMask m))  = shows b . ('/':) . shows m++parseIpv6Block :: T.Text -> Either T.Text Ipv6Block+parseIpv6Block t =+  case T.unpack <$> T.split (== '/') t of+    [addr, mask] ->+      case readMaybe addr :: Maybe Ipv6Address of+        Just ipv6 ->+          case readMaybe mask of+            Just maskv6 -> Right $ Ipv6Block ipv6 maskv6+            Nothing     -> Left "cannot read mask"+        Nothing -> Left "cannot read addr"+    _ -> Left "invalid input string"++masksIpv6 :: Word8 -> [Word32]+masksIpv6 m =+  let e = 0xFFFFFFFF :: Word32+      -- bits: number of bits which should be 1+      maskValue bits = e `shiftR` (32 - bits) in+    if m < 32 then+      [maskValue (32 - fromIntegral m), e, e, e]+    else if m < 64 then+      [0, maskValue (64 - fromIntegral m), e, e]+    else if m < 96 then+      [0, 0, maskValue (96 - fromIntegral m), e]+    else if m < 128 then+      [0, 0, 0, maskValue (128 - fromIntegral m)]+    else+      [0, 0, 0, 0]++isValidIpv6Block :: Ipv6Block -> Bool+isValidIpv6Block (Ipv6Block b (Ipv6NetMask m)) =+  let lt = masksIpv6 m+      ipv6 = I.word32x4ToWords (words b) in+    ipv6 == zipWith (.&.) ipv6 (zipWith xor ipv6 lt)++ipv4BlockToMappedIpv6Block :: I4.Ipv4Block -> Ipv6Block+ipv4BlockToMappedIpv6Block (I4.Ipv4Block b m) =+  -- RFC-4291, "IPv4-Mapped IPv6 Address"+  Ipv6Block (Ipv6Address (0, 0, 0xFFFF, I4.word b)) (Ipv6NetMask (96 + I4.word8 m))
− src/HaskellWorks/Data/Network/Ip/Parser/Text.hs
@@ -1,10 +0,0 @@-module HaskellWorks.Data.Network.Ip.Parser.Text-  ( ipv4Address-  ) where--import qualified Data.Attoparsec.Text                  as AP-import qualified HaskellWorks.Data.Network.Ip.Internal as I-import qualified HaskellWorks.Data.Network.Ip.Type     as HW--ipv4Address :: AP.Parser HW.Ipv4Address-ipv4Address = HW.Ipv4Address <$> I.ipv4Address
src/HaskellWorks/Data/Network/Ip/Type.hs view
@@ -1,75 +1,14 @@-{-# LANGUAGE DeriveGeneric              #-} {-# LANGUAGE DuplicateRecordFields      #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE InstanceSigs               #-}-{-# LANGUAGE OverloadedStrings          #-}  module HaskellWorks.Data.Network.Ip.Type-  ( Ipv4Address(..)-  , Ipv4NetMask(..)-  , Ipv4Block(..)+  ( I4.Ipv4Address(..)+  , I4.Ipv4NetMask(..)+  , I4.Ipv4Block(..)+  , I6.Ipv6Address(..)+  , I6.Ipv6NetMask(..)+  , I6.Ipv6Block(..)   ) where -import Data.Maybe-import Data.Word-import GHC.Generics-import HaskellWorks.Data.Bits.BitWise-import Control.Monad--import qualified Data.Attoparsec.Text                  as AP-import qualified Data.Bits                             as B-import qualified Data.Text                             as T-import qualified HaskellWorks.Data.Network.Ip.Internal as I-import qualified Text.ParserCombinators.ReadPrec       as RP--newtype Ipv4Address = Ipv4Address-  { word :: Word32-  } deriving (Enum, Eq, Ord, Generic)--instance Show Ipv4Address where-  showsPrec _ (Ipv4Address w) =-    shows ((w .>. 24) .&. 0xff) . ('.':) .-    shows ((w .>. 16) .&. 0xff) . ('.':) .-    shows ((w .>.  8) .&. 0xff) . ('.':) .-    shows ( w         .&. 0xff)--instance Read Ipv4Address where-  readsPrec :: Int -> String -> [(Ipv4Address, String)]-  readsPrec _ s = case AP.parseWith (return mempty) (I.whitespace *> I.ipv4Address) (T.pack s) of-    Just result -> case result of-      AP.Done i r   -> [(Ipv4Address r, T.unpack i)]-      AP.Partial _  -> []-      AP.Fail a b c -> []-    Nothing -> []--newtype Ipv4NetMask = Ipv4NetMask-  { word :: Word8-  } deriving (Enum, Eq, Ord, Show, Generic)--data Ipv4Block = Ipv4Block-  { base :: !Ipv4Address-  , mask :: !Ipv4NetMask-  } deriving (Eq, Ord)--instance Show Ipv4Block where-  showsPrec _ (Ipv4Block b (Ipv4NetMask m)) = shows b . ('/':) . shows m--instance Read Ipv4Block where-  readsPrec :: Int -> String -> [(Ipv4Block, String)]-  readsPrec _ s = case AP.parseWith (return mempty) (I.whitespace *> I.ipv4Block) (T.pack s) of-    Just result -> case result of-      AP.Done i (a, m) ->-        case validIpv4Block $ Ipv4Block (Ipv4Address a) (Ipv4NetMask m) of-          Just b  -> [(b, T.unpack i)]-          Nothing -> []-      AP.Partial _     -> []-      AP.Fail a b c    -> []-    Nothing -> []---- shift the address left by the amount of mask bits to reveal only host bits--- if any bits left are non-zero, then the mask is not big enough-validIpv4Block :: Ipv4Block -> Maybe Ipv4Block-validIpv4Block b@(Ipv4Block (Ipv4Address word) (Ipv4NetMask mask)) =-  if word `B.shiftL` fromIntegral mask `B.xor` 0 == 0-    then pure b-    else Nothing+import qualified HaskellWorks.Data.Network.Ip.Ipv4 as I4+import qualified HaskellWorks.Data.Network.Ip.Ipv6 as I6
test/HaskellWorks/Data/Network/IpSpec.hs view
@@ -3,6 +3,7 @@ module HaskellWorks.Data.Network.IpSpec (spec) where  import HaskellWorks.Data.Network.Ip+import HaskellWorks.Data.Network.Ip.Ipv4 import HaskellWorks.Data.Network.Ip.Internal import HaskellWorks.Hspec.Hedgehog import Hedgehog@@ -24,23 +25,23 @@       AP.parseOnly octet (T.pack . show $ b) === Right b    describe "Ipv4Address" $ do-    it "should implement show" $ require $ property $ do+    it "should implement show" $ requireTest $ do       show (Ipv4Address 0x000000ff) === "0.0.0.255"       show (Ipv4Address 0x0000ff00) === "0.0.255.0"       show (Ipv4Address 0x00ff0000) === "0.255.0.0"       show (Ipv4Address 0xff000000) === "255.0.0.0" -    it "should implement read" $ require $ property $ do+    it "should implement read" $ requireTest $ do       read "1.2.3.4"      === Ipv4Address 0x01020304       read "10.20.30.40"  === Ipv4Address 0x0a141e28       read "1.2.3.12"     === Ipv4Address 0x0102030c       read "1.2.3.160"    === Ipv4Address 0x010203a0 -    it "should be possible to extract the octets" $ require $ property $ do+    it "should be possible to extract the octets" $ requireTest $ do       ipv4AddressToWords (Ipv4Address 0x01020304) === (1, 2, 3, 4)    describe "Ipv4Block" $ do-    it "should implement show" $ require $ property $ do+    it "should implement show" $ requireTest $ do       show (Ipv4Block (Ipv4Address 0x000000ff) (Ipv4NetMask 32)) === "0.0.0.255/32"       show (Ipv4Block (Ipv4Address 0x0000ff00) (Ipv4NetMask 32)) === "0.0.255.0/32"       show (Ipv4Block (Ipv4Address 0x00ff0000) (Ipv4NetMask 32)) === "0.255.0.0/32"@@ -60,22 +61,22 @@       show (firstIpv4Address $ Ipv4Block (Ipv4Address 0xff000000) (Ipv4NetMask 21)) === "255.0.0.0"       show (lastIpv4Address  $ Ipv4Block (Ipv4Address 0xff000000) (Ipv4NetMask 21)) === "255.0.7.255" -    it "should implement read" $ require $ property $ do+    it "should implement read" $ requireTest $ do       read "1.0.0.0/8"  === Ipv4Block (Ipv4Address 0x01000000) (Ipv4NetMask 8)       read "1.2.0.0/16" === Ipv4Block (Ipv4Address 0x01020000) (Ipv4NetMask 16)       read "1.2.3.4/32" === Ipv4Block (Ipv4Address 0x01020304) (Ipv4NetMask 32) -    it "should implement splitBlock" $ require $ property $ do+    it "should implement splitBlock" $ requireTest $ do       splitBlock (Ipv4Block (Ipv4Address 0x00000000) (Ipv4NetMask 32)) === Nothing       splitBlock (Ipv4Block (Ipv4Address 0x00000000) (Ipv4NetMask 31)) === Just (Ipv4Block (Ipv4Address 0x00000000) (Ipv4NetMask 32), Ipv4Block (Ipv4Address 0x00000001) (Ipv4NetMask 32))       splitBlock (Ipv4Block (Ipv4Address 0x00000000) (Ipv4NetMask 30)) === Just (Ipv4Block (Ipv4Address 0x00000000) (Ipv4NetMask 31), Ipv4Block (Ipv4Address 0x00000002) (Ipv4NetMask 31))       splitBlock (Ipv4Block (Ipv4Address 0x00000000) (Ipv4NetMask  0)) === Just (Ipv4Block (Ipv4Address 0x00000000) (Ipv4NetMask  1), Ipv4Block (Ipv4Address 0x80000000) (Ipv4NetMask  1)) -    it "should implement blockSize" $ require $ property $ do+    it "should implement blockSize" $ requireTest $ do       blockSize (Ipv4Block (Ipv4Address 0x00000000) (Ipv4NetMask 32)) === 1       blockSize (Ipv4Block (Ipv4Address 0x00000000) (Ipv4NetMask  0)) === 0x100000000 -    it "should validate masks" $ require $ property $ do+    it "should validate masks" $ requireTest $ do       (TR.readMaybe "1.2.3.4/8"  :: Maybe Ipv4Block) === Nothing       (TR.readMaybe "1.2.3.4/0"  :: Maybe Ipv4Block) === Nothing       (TR.readMaybe "1.2.3.4/32" :: Maybe Ipv4Block) === (Just $ Ipv4Block (Ipv4Address 0x01020304) (Ipv4NetMask 32))