packages feed

ip 1.6.0 → 1.7.0

raw patch · 8 files changed

+55/−158 lines, 8 filesdep ~basedep ~byteslicedep ~vectorPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, byteslice, vector

API changes (from Hackage documentation)

- Net.IPv4: instance Data.Bits.Bits Net.IPv4.IPv4Range
- Net.IPv4: instance Data.Bits.FiniteBits Net.IPv4.IPv4Range
- Net.IPv6: instance GHC.Num.Num Net.IPv6.IPv6
- Net.IPv6: instance GHC.Real.Integral Net.IPv6.IPv6
- Net.IPv6: instance GHC.Real.Real Net.IPv6.IPv6
+ Net.IP: instance Data.Data.Data Net.IP.IP
+ Net.IP: instance GHC.Arr.Ix Net.IP.IP
+ Net.IPv4: instance Data.Data.Data Net.IPv4.IPv4
+ Net.IPv4: instance Data.Data.Data Net.IPv4.IPv4Range
+ Net.IPv4: instance GHC.Arr.Ix Net.IPv4.IPv4
+ Net.IPv6: instance Data.Aeson.Types.FromJSON.FromJSON Net.IPv6.IPv6Range
+ Net.IPv6: instance Data.Aeson.Types.ToJSON.ToJSON Net.IPv6.IPv6Range
+ Net.IPv6: instance Data.Data.Data Net.IPv6.IPv6
+ Net.IPv6: instance Data.Data.Data Net.IPv6.IPv6Range
+ Net.IPv6: instance GHC.Arr.Ix Net.IPv6.IPv6
+ Net.Mac: instance Data.Data.Data Net.Mac.Mac
+ Net.Mac: instance Data.Data.Data Net.Mac.MacCodec
+ Net.Mac: instance Data.Data.Data Net.Mac.MacGrouping
+ Net.Mac: instance GHC.Arr.Ix Net.Mac.Mac

Files

ip.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: ip-version: 1.6.0+version: 1.7.0 synopsis: Library for IP and MAC addresses homepage: https://github.com/andrewthad/haskell-ip#readme license: BSD-3-Clause@@ -48,7 +48,7 @@   build-depends:     , aeson >= 1.0 && < 1.5     , attoparsec >= 0.13 && < 0.14-    , base >= 4.9.1.0 && < 5+    , base >= 4.9 && < 5     , byteslice >= 0.1.2 && < 0.2     , bytesmith >= 0.3 && < 0.4     , bytestring >= 0.10.8 && < 0.11@@ -56,7 +56,7 @@     , hashable >= 1.2 && < 1.4     , natural-arithmetic >= 0.1 && <0.2     , primitive >= 0.6.4 && < 0.8-    , small-bytearray-builder >= 0.2.1 && <0.3+    , small-bytearray-builder >= 0.2.1 && <0.4     , text >= 1.2 && < 1.3     , text-short >= 0.1.3 && < 0.2     , vector >= 0.11 && < 0.13@@ -101,7 +101,6 @@     , ip     , wide-word   other-modules:-    Net.IPv4.RangeSpec     Net.IPv4Spec   ghc-options: -Wall -O2   default-language: Haskell2010@@ -117,6 +116,7 @@     , doctest >= 0.10     , ip     , wide-word+    , vector   default-language:    Haskell2010  benchmark criterion
src/Net/IP.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} @@ -56,6 +57,8 @@ import Data.Aeson (FromJSON(..),ToJSON(..)) import Data.Bits import Data.Coerce (coerce)+import Data.Data (Data)+import Data.Ix (Ix) import Data.Text (Text) import Data.WideWord (Word128(..)) import Data.Word (Word8,Word16)@@ -222,7 +225,7 @@ --   of this type. All functions and typeclass methods that convert --   'IP' values to text will display it as an 'IPv4' address if possible. newtype IP = IP { getIP :: IPv6 }-  deriving (Eq,Ord,Generic)+  deriving (Eq,Ord,Generic,Ix,Data)  instance NFData IP 
src/Net/IPv4.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MagicHash #-}@@ -94,10 +95,12 @@ import Control.Monad.ST (ST,runST) import Data.Aeson (FromJSON(..),ToJSON(..)) import Data.Aeson (ToJSONKey(..),FromJSONKey(..),ToJSONKeyFunction(..),FromJSONKeyFunction(..))-import Data.Bits ((.&.),(.|.),shiftR,shiftL,unsafeShiftR,complement,shift)+import Data.Bits (Bits(..)) import Data.ByteString (ByteString) import Data.Coerce (coerce)+import Data.Data (Data) import Data.Hashable+import Data.Ix (Ix) import Data.Primitive.Types (Prim) import Data.Text (Text) import Data.Text.Encoding (decodeUtf8')@@ -156,7 +159,9 @@ -- >>> import qualified Data.Text.IO as T -- >>> instance Arbitrary IPv4 where { arbitrary = fmap IPv4 arbitrary } -- >>> instance Arbitrary IPv4Range where { arbitrary = IPv4Range <$> arbitrary <*> arbitrary }+-- >>> import qualified Data.Bytes.Chunks as Chunks + -- | Create an 'IPv4' address from four octets. The first argument --   is the most significant octet. The last argument is the least --   significant. Since IP addresses are commonly written using dot-decimal@@ -452,7 +457,7 @@  -- | Encode an 'IPv4' address as a unbounded byte array builder. ----- >>> UB.run 1 (byteArrayBuilderUtf8 (fromOctets 192 168 2 13))+-- >>> Chunks.concat (UB.run 1 (byteArrayBuilderUtf8 (fromOctets 192 168 2 13))) -- [0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x32, 0x2e, 0x31, 0x33] -- -- Note that period is encoded by UTF-8 as @0x2e@.@@ -533,11 +538,11 @@ -- convert between this and the lifted 'IPv4'. type IPv4# = Word# --- | Convert an unboxed IPv4 address to a boxed one. +-- | Convert an unboxed IPv4 address to a boxed one. box :: IPv4# -> IPv4 box w = IPv4 (W32# w) --- | Convert a boxed IPv4 address to an unboxed one. +-- | Convert a boxed IPv4 address to an unboxed one. unbox :: IPv4 -> IPv4# unbox (IPv4 (W32# w)) = w @@ -546,7 +551,7 @@ --   convert the underlying 'Word32' from host byte order to network byte --   order. newtype IPv4 = IPv4 { getIPv4 :: Word32 }-  deriving (Eq,Ord,Enum,Bounded,Hashable,Generic,Prim,Storable)+  deriving (Bits.Bits,Bounded,Data,Enum,Eq,Bits.FiniteBits,Generic,Hashable,Ix,Ord,Prim,Storable)  instance NFData IPv4 @@ -642,28 +647,6 @@   Nothing -> fail "Could not parse IPv4 address"   Just addr -> return addr -ipv4Bitwise :: (Word32 -> Word32 -> Word32) -> IPv4 -> IPv4 -> IPv4-ipv4Bitwise fun l r = IPv4 $ (getIPv4 l) `fun` (getIPv4 r)---- | Note: we use network order (big endian) as opposed to host order (little---   endian) which differs from the underlying IPv4 type representation.-instance Bits.Bits IPv4 where-    (.&.) = ipv4Bitwise (.&.)-    (.|.) = ipv4Bitwise (.|.)-    xor = ipv4Bitwise Bits.xor-    complement = IPv4 . Bits.complement . getIPv4-    shift ip i = IPv4 $ Bits.shift (getIPv4 ip) i-    rotate ip i = IPv4 $ Bits.rotate (getIPv4 ip) i-    bitSize = Bits.finiteBitSize-    bitSizeMaybe = Bits.bitSizeMaybe . getIPv4-    isSigned = Bits.isSigned . getIPv4-    testBit ip i = Bits.testBit (getIPv4 ip) $ Bits.finiteBitSize ip - 1 - i-    bit i = IPv4 $ Bits.bit $ Bits.finiteBitSize any - 1 - i-    popCount = Bits.popCount . getIPv4--instance Bits.FiniteBits IPv4 where-    finiteBitSize = Bits.finiteBitSize . getIPv4- ------------------------------------ -- Internal functions, not exported ------------------------------------@@ -1074,7 +1057,7 @@ data IPv4Range = IPv4Range   { ipv4RangeBase   :: {-# UNPACK #-} !IPv4   , ipv4RangeLength :: {-# UNPACK #-} !Word8-  } deriving (Eq,Ord,Show,Read,Generic)+  } deriving (Eq,Ord,Show,Read,Generic,Data)  instance NFData IPv4Range instance Hashable IPv4Range@@ -1196,47 +1179,6 @@   elemseq _ (IPv4Range a b)       = GVector.elemseq (undefined :: UVector.Vector a) a         . GVector.elemseq (undefined :: UVector.Vector b) b--rangeBitwise :: (IPv4 -> IPv4 -> IPv4) -> IPv4Range -> IPv4Range -> IPv4Range-rangeBitwise fun l r = range ip len-  where-    -- Normalise first-    l' = normalize l-    r' = normalize r-    ip = (ipv4RangeBase l') `fun` (ipv4RangeBase r')-    len = maximum [ipv4RangeLength l, ipv4RangeLength r]--rangeRebase :: (IPv4 -> IPv4) -> IPv4Range -> IPv4Range-rangeRebase fun r = range (fun $ ipv4RangeBase r) (ipv4RangeLength r)---- | Notes:------     * bit operations use network order (big endian),------     * do not operate on host bits,------     * return a normalized range dropping host bits,------     * and "promote operands" by extending the length to the larger of two---       ranges.----instance Bits.Bits IPv4Range where-  (.&.) = rangeBitwise (.&.)-  (.|.) = rangeBitwise (.|.)-  xor = rangeBitwise Bits.xor-  complement = rangeRebase Bits.complement-  shift r i = rangeRebase (flip Bits.shift i) r-  rotate r i = rangeRebase (flip Bits.rotate i) r-  bitSize = Bits.finiteBitSize-  bitSizeMaybe = Just . Bits.finiteBitSize-  isSigned = Bits.isSigned . ipv4RangeBase-  testBit ip i = Bits.testBit (ipv4RangeBase ip) i-  bit i = IPv4Range (Bits.bit i) $ fromIntegral $ i + 1-  popCount = Bits.popCount . ipv4RangeBase . normalize---- | Note: the size is determined by the range length-instance Bits.FiniteBits IPv4Range where-  finiteBitSize = fromIntegral . ipv4RangeLength  ----------------- -- Internal Stuff
src/Net/IPv6.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE InstanceSigs #-}@@ -66,9 +67,12 @@  import Control.Applicative import Control.DeepSeq (NFData)+import Control.Monad (mzero) import Control.Monad.ST (ST) import Data.Bits import Data.Char (chr)+import Data.Data (Data)+import Data.Ix (Ix) import Data.List (intercalate, group) import Data.Primitive (MutablePrimArray) import Data.Primitive.Types (Prim)@@ -115,7 +119,7 @@  -- | A 128-bit Internet Protocol version 6 address. newtype IPv6 = IPv6 { getIPv6 :: Word128 }-  deriving (Bounded,Enum,Eq,Integral,Num,Ord,Real,Storable,Bits,FiniteBits,NFData,Prim)+  deriving (Bounded,Enum,Eq,Ord,Storable,Bits,FiniteBits,NFData,Prim,Ix,Data)  instance Show IPv6 where   showsPrec p addr = showParen (p > 10)@@ -749,9 +753,18 @@ data IPv6Range = IPv6Range   { ipv6RangeBase   :: {-# UNPACK #-} !IPv6   , ipv6RangeLength :: {-# UNPACK #-} !Word8-  } deriving (Eq,Ord,Show,Read,Generic)+  } deriving (Eq,Ord,Show,Read,Generic,Data)  instance NFData IPv6Range++instance Aeson.ToJSON IPv6Range where+  toJSON = Aeson.String . encodeRange++instance Aeson.FromJSON IPv6Range where+  parseJSON (Aeson.String t) = case decodeRange t of+    Nothing -> fail "Could not decodeRange IPv6 range"+    Just res -> return res+  parseJSON _ = mzero  mask128 :: IPv6 mask128 = maxBound
src/Net/Mac.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE InstanceSigs #-}@@ -53,7 +54,9 @@ import Data.Bits ((.|.),unsafeShiftL,unsafeShiftR,(.&.)) import Data.ByteString (ByteString) import Data.Char (ord,chr)+import Data.Data (Data) import Data.Hashable (Hashable)+import Data.Ix (Ix) import Data.Primitive.Types (Prim(..)) #if !MIN_VERSION_base(4,11,0) import Data.Semigroup ((<>))@@ -607,7 +610,7 @@ --   type. It is not considered part of the stable API, and it --   allows you to construct invalid MAC addresses. newtype Mac = Mac Word64-  deriving (Eq,Ord,Generic)+  deriving (Eq,Ord,Generic,Ix,Data)  instance NFData Mac @@ -737,7 +740,7 @@ data MacCodec = MacCodec   { macCodecGrouping :: !MacGrouping   , macCodecUpperCase :: !Bool-  } deriving (Eq,Ord,Show,Read,Generic)+  } deriving (Eq,Ord,Show,Read,Generic,Data)  -- | The format expected by the mac address parser. The 'Word8' taken --   by some of these constructors is the ascii value of the character@@ -748,7 +751,7 @@   | MacGroupingTriples !Char -- ^ Three-character groups, @24B-F0A-025-829@   | MacGroupingQuadruples !Char -- ^ Four-character groups, @A220.0745.CAC7@   | MacGroupingNoSeparator -- ^ No separator, @24AF4B5B0780@-  deriving (Eq,Ord,Show,Read,Generic)+  deriving (Eq,Ord,Show,Read,Generic,Data)  instance Hashable Mac 
− test/Net/IPv4/RangeSpec.hs
@@ -1,67 +0,0 @@-{-# OPTIONS_GHC -Wno-deprecations #-}-module Net.IPv4.RangeSpec (spec) where-import Prelude hiding (any)-import Data.Bits-import Net.IPv4-import Test.Hspec--spec :: Spec-spec = parallel $ do-  describe "Bits" $ do-    context "underlying IPv4 imlementation used correctly" $ do-      let host = range (ipv4 255 255 0 0) 32-          broadH = range broadcast 32-          negBroadH = range (ipv4 0 0 255 255) 32-      it ".&." $ do-        host .&. broadH `shouldBe` host-      it ".|." $ do-        host .|. broadH `shouldBe` broadH-      it "xor" $ do-        host `xor` broadH `shouldBe` negBroadH-      it "complement" $ do-        complement host `shouldBe` negBroadH-      it "shift" $ do-        shift host 8 `shouldBe` range (ipv4 255 0 0 0) 32-      it "rotate" $ do-        rotate host 8 `shouldBe` range (ipv4 255 0 0 255) 32-      it "isSigned" $ do-        isSigned host `shouldBe` False-    context "size operations use length correctly" $ do-      it "bitSize" $ do-          bitSize (range any 8) `shouldBe` 8-          bitSize (range any 15) `shouldBe` 15-          bitSize (range any 32) `shouldBe` 32-      it "bitSizeMaybe" $ do-          bitSizeMaybe (range broadcast 0) `shouldBe` Just 0-          bitSizeMaybe (range broadcast 24) `shouldBe` Just 24-          bitSizeMaybe (range broadcast 31) `shouldBe` Just 31-      it "testBit" $ do-        let prefix = range loopback 8-        testBit prefix <$> [0..31] `shouldBe`-          -- Note: final bit is False not True-          [ False, True,  True,  True,  True,  True,  True,  True-          , False, False, False, False, False, False, False, False-          , False, False, False, False, False, False, False, False-          , False, False, False, False, False, False, False, False]-      it "bit" $ do-        bit 0 `shouldBe` range (ipv4 128 0 0 0) 1-        bit 1 `shouldBe` range (ipv4 64 0 0 0) 2-        bit 31 `shouldBe` range (ipv4 0 0 0 1) 32-      it "popCount" $ do-        popCount (range any 0) `shouldBe` 0-        popCount (range broadcast 0) `shouldBe` 0-        popCount (range loopback 8) `shouldBe` 7-        popCount (range loopback 32) `shouldBe` 8-    context "operates on network bits only" $ do-      it "bitwise: same length" $ do-        (IPv4Range broadcast 16) .&. (IPv4Range broadcast 16)-          `shouldBe` (IPv4Range (ipv4 255 255 0 0) 16)-      it "bitwise: differing lengths ignoring host bits" $ do-        (IPv4Range broadcast 8) .&. (IPv4Range broadcast 16)-          `shouldBe` (IPv4Range (ipv4 255 0 0 0) 16)-      it "rebase: ignores host bits" $ do-        complement (IPv4Range loopback 16)-          `shouldBe` (IPv4Range (ipv4 128 255 0 0) 16)-  describe "FiniteBits" $ do-    it "finiteBitSize" $ do-      finiteBitSize . (range loopback) <$> [0..31] `shouldBe` [0..31]
test/Net/IPv4Spec.hs view
@@ -49,14 +49,14 @@             isSigned broadcast `shouldBe` False         it "testBit" $ do             testBit loopback <$> [0..31] `shouldBe`-                [ False, True,  True,  True,  True,  True,  True,  True-                , False, False, False, False, False, False, False, False-                , False, False, False, False, False, False, False, False-                , False, False, False, False, False, False, False, True]+              [ True, False, False, False, False, False, False, False+              , False, False, False, False, False, False, False, False+              , False, False, False, False, False, False, False, False+              , True, True, True, True, True, True, True, False ]         it "bit" $ do-            bit 0 `shouldBe` ipv4 128 0 0 0-            bit 1 `shouldBe` ipv4 64 0 0 0-            bit 31 `shouldBe` ipv4 0 0 0 1+            bit 0 `shouldBe` ipv4 0 0 0 1+            bit 1 `shouldBe` ipv4 0 0 0 2+            bit 31 `shouldBe` ipv4 128 0 0 0         it "popCount" $ do             popCount any `shouldBe` 0             popCount loopback `shouldBe` 8
test/Test.hs view
@@ -16,7 +16,7 @@ import Numeric (showHex) import Test.QuickCheck.Property (failed,succeeded,Result(..)) import Data.Bifunctor-import Test.QuickCheck.Classes (Laws(..),jsonLaws,showReadLaws,primLaws,boundedEnumLaws)+import Test.QuickCheck.Classes (Laws(..),jsonLaws,showReadLaws,primLaws,boundedEnumLaws,bitsLaws) import qualified Test.Tasty.HUnit as PH  import Net.Types (IP,IPv4(..),IPv4Range(..),Mac(..),IPv6(..),MacGrouping(..),MacCodec(..),IPv6Range(..))@@ -96,7 +96,7 @@       [ PH.testCase "Parser Test Cases" testIPv4Parser       ]     , testGroup "IPv6 encode/decode"-      [ PH.testCase "Parser Test Cases" $ testIPv6Parser $ \str -> +      [ PH.testCase "Parser Test Cases" $ testIPv6Parser $ \str ->           either (\_ -> Nothing) (Just . HexIPv6)             (AT.parseOnly               (IPv6.parser <* AT.endOfInput)@@ -146,19 +146,23 @@     [ testGroup "IPv4"       [ lawsToTest (jsonLaws (Proxy :: Proxy IPv4))       , lawsToTest (showReadLaws (Proxy :: Proxy IPv4))-      -- , lawsToTest (bitsLaws (Proxy :: Proxy IPv4))+       , lawsToTest (bitsLaws (Proxy :: Proxy IPv4))       ]     , testGroup "IPv4Range"       [ lawsToTest (jsonLaws (Proxy :: Proxy IPv4Range))       , lawsToTest (showReadLaws (Proxy :: Proxy IPv4Range))-      -- , lawsToTest (bitsLaws (Proxy :: Proxy IPv4Range))       ]     , testGroup "IPv6"       [ lawsToTest (jsonLaws (Proxy :: Proxy IPv6))       , lawsToTest (showReadLaws (Proxy :: Proxy IPv6))       , lawsToTest (primLaws (Proxy :: Proxy IPv6))       , lawsToTest (boundedEnumLaws (Proxy :: Proxy IPv6))+      , lawsToTest (bitsLaws (Proxy :: Proxy IPv6))       ]+    , testGroup "IPv6Range"+      [ lawsToTest (jsonLaws (Proxy :: Proxy IPv6Range))+      , lawsToTest (showReadLaws (Proxy :: Proxy IPv6Range))+      ]     , testGroup "IP"       [ lawsToTest (jsonLaws (Proxy :: Proxy IP))       , lawsToTest (showReadLaws (Proxy :: Proxy IP))@@ -472,7 +476,6 @@   shrink (IPv6Range addr mask) = liftA2 IPv6.range     (shrink addr)     (filter (/= mask) [0,div mask 2,if mask > 0 then mask - 1 else 0])-      instance Arbitrary MacCodec where   arbitrary = MacCodec <$> arbitrary <*> arbitrary