packages feed

ip 0.8 → 0.8.1

raw patch · 7 files changed

+148/−121 lines, 7 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Net.Mac: Mac :: {-# UNPACK #-} !Word16 -> {-# UNPACK #-} !Word32 -> Mac
- Net.Mac: [macA] :: Mac -> {-# UNPACK #-} !Word16
- Net.Mac: [macB] :: Mac -> {-# UNPACK #-} !Word32
- Net.Mac: bytestringParser :: Parser Mac
- Net.Mac: data Mac
- Net.Mac: fromOctets' :: Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> Mac
- Net.Mac: fromText :: Text -> Maybe Mac
- Net.Mac: fromText' :: Text -> Either String Mac
- Net.Mac: instance Data.Aeson.Types.Class.FromJSON Net.Mac.Mac
- Net.Mac: instance Data.Aeson.Types.Class.ToJSON Net.Mac.Mac
- Net.Mac: instance Data.Hashable.Class.Hashable Net.Mac.Mac
- Net.Mac: instance GHC.Classes.Eq Net.Mac.Mac
- Net.Mac: instance GHC.Classes.Ord Net.Mac.Mac
- Net.Mac: instance GHC.Generics.Generic Net.Mac.Mac
- Net.Mac: instance GHC.Read.Read Net.Mac.Mac
- Net.Mac: instance GHC.Show.Show Net.Mac.Mac
- Net.Mac: textParser :: Parser Mac
- Net.Mac: toText :: Mac -> Text
- Net.Mac: toTextBuilder :: Mac -> Builder
+ Net.Internal: macFromText :: (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Text -> Maybe a
+ Net.Internal: macFromText' :: (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Text -> Either String a
+ Net.Internal: macTextParser :: (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Parser a
+ Net.Internal: macToText :: Word16 -> Word32 -> Text
+ Net.Internal: macToTextBuilder :: Word16 -> Word32 -> Builder
+ Net.Mac: fromOctetsNoCast :: Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> Mac
+ Net.Types: Mac :: {-# UNPACK #-} !Word16 -> {-# UNPACK #-} !Word32 -> Mac
+ Net.Types: [macA] :: Mac -> {-# UNPACK #-} !Word16
+ Net.Types: [macB] :: Mac -> {-# UNPACK #-} !Word32
+ Net.Types: data Mac
+ Net.Types: instance Data.Aeson.Types.Class.FromJSON Net.Types.Mac
+ Net.Types: instance Data.Aeson.Types.Class.ToJSON Net.Types.Mac
+ Net.Types: instance Data.Hashable.Class.Hashable Net.Types.Mac
+ Net.Types: instance Data.Primitive.Types.Prim Net.Types.IPv4
+ Net.Types: instance Data.Vector.Generic.Base.Vector Data.Vector.Unboxed.Base.Vector Net.Types.IPv4
+ Net.Types: instance Data.Vector.Generic.Mutable.Base.MVector Data.Vector.Unboxed.Base.MVector Net.Types.IPv4
+ Net.Types: instance Data.Vector.Unboxed.Base.Unbox Net.Types.IPv4
+ Net.Types: instance GHC.Classes.Eq Net.Types.Mac
+ Net.Types: instance GHC.Classes.Ord Net.Types.Mac
+ Net.Types: instance GHC.Generics.Generic Net.Types.Mac
+ Net.Types: instance GHC.Read.Read Net.Types.Mac
+ Net.Types: instance GHC.Show.Show Net.Types.Mac

Files

ip.cabal view
@@ -1,5 +1,5 @@ name:                ip-version:             0.8+version:             0.8.1 synopsis:            Library for IP and MAC addresses description:         Please see README.md homepage:            https://github.com/andrewthad/haskell-ip#readme
src/Net/IPv4.hs view
@@ -1,8 +1,3 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE InstanceSigs #-}-{-# LANGUAGE ScopedTypeVariables #-}- {-| An IPv4 data type      This module provides the IPv4 data type and functions for working@@ -49,7 +44,6 @@ import qualified Net.Internal           as Internal import qualified Data.Text.Lazy         as LText import qualified Data.Text.IO           as Text-import qualified Data.Vector.Unboxed    as UVector import qualified Data.ByteString        as ByteString import qualified Data.ByteString.Unsafe as ByteString 
src/Net/Internal.hs view
@@ -15,6 +15,7 @@ import qualified Data.ByteString        as ByteString import qualified Data.ByteString.Unsafe as ByteString import qualified Data.Text.Lazy.Builder as TBuilder+import qualified Data.Text.Lazy.Builder.Int as TBuilder  attoparsecParseJSON :: AT.Parser a -> Aeson.Value -> Aeson.Parser a attoparsecParseJSON p v =@@ -207,4 +208,48 @@ -- r1,r2,r3,r4,r5,r6 :: Word32 -- r1 = fromOctets' 0 0 0 0 +macTextParser :: (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> AT.Parser a+macTextParser f = f+  <$> (AT.hexadecimal >>= limitSize)+  <*  AT.char ':'+  <*> (AT.hexadecimal >>= limitSize)+  <*  AT.char ':'+  <*> (AT.hexadecimal >>= limitSize)+  <*  AT.char ':'+  <*> (AT.hexadecimal >>= limitSize)+  <*  AT.char ':'+  <*> (AT.hexadecimal >>= limitSize)+  <*  AT.char ':'+  <*> (AT.hexadecimal >>= limitSize)+  where+  limitSize i =+    if i > 255+      then fail "All octets in a mac address must be between 00 and FF"+      else return i++macToText :: Word16 -> Word32 -> Text+macToText a b = LText.toStrict (TBuilder.toLazyText (macToTextBuilder a b))++macToTextBuilder :: Word16 -> Word32 -> TBuilder.Builder+macToTextBuilder a b =+  TBuilder.hexadecimal (255 .&. shiftR a 8 )+  <> colon+  <> TBuilder.hexadecimal (255 .&. a )+  <> colon+  <> TBuilder.hexadecimal (255 .&. shiftR b 24 )+  <> colon+  <> TBuilder.hexadecimal (255 .&. shiftR b 16 )+  <> colon+  <> TBuilder.hexadecimal (255 .&. shiftR b 8 )+  <> colon+  <> TBuilder.hexadecimal (255 .&. b)+  where colon = TBuilder.singleton ':'++macFromText :: (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Text -> Maybe a+macFromText f = rightToMaybe . macFromText' f+{-# INLINE macFromText #-}++macFromText' :: (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Text -> Either String a+macFromText' f = AT.parseOnly (macTextParser f <* AT.endOfInput)+{-# INLINE macFromText' #-} 
src/Net/Mac.hs view
@@ -1,8 +1,12 @@  {-# LANGUAGE DeriveGeneric #-}  {-# LANGUAGE GeneralizedNewtypeDeriving #-} -module Net.Mac where+module Net.Mac+  ( fromOctets+  , fromOctetsNoCast+  ) where +import Net.Types (Mac(..)) import Data.Text (Text) import Data.Hashable (Hashable) import GHC.Generics (Generic)@@ -18,91 +22,15 @@ import qualified Data.Aeson as Aeson import qualified Data.Text.Lazy as LText -data Mac = Mac-  { macA :: {-# UNPACK #-} !Word16-  , macB :: {-# UNPACK #-} !Word32-  }-  deriving (Eq,Ord,Show,Read,Generic)--instance Hashable Mac--instance ToJSON Mac where-  toJSON = Aeson.String . toText--instance FromJSON Mac where-  parseJSON = attoparsecParseJSON (textParser <* AT.endOfInput)--toText :: Mac -> Text-toText = LText.toStrict . TBuilder.toLazyText . toTextBuilder--fromText :: Text -> Maybe Mac-fromText = rightToMaybe . fromText'--fromText' :: Text -> Either String Mac-fromText' t = AT.parseOnly (textParser <* AT.endOfInput) t--toTextBuilder :: Mac -> TBuilder.Builder-toTextBuilder (Mac a b) =-  hexadecimal (255 .&. shiftR a 8 )-  <> colon-  <> hexadecimal (255 .&. a )-  <> colon-  <> hexadecimal (255 .&. shiftR b 24 )-  <> colon-  <> hexadecimal (255 .&. shiftR b 16 )-  <> colon-  <> hexadecimal (255 .&. shiftR b 8 )-  <> colon-  <> hexadecimal (255 .&. b)-  where colon = TBuilder.singleton ':'---- | This does not do an endOfInput check-textParser :: AT.Parser Mac-textParser = fromOctets'-  <$> (AT.hexadecimal >>= limitSize)-  <*  AT.char ':'-  <*> (AT.hexadecimal >>= limitSize)-  <*  AT.char ':'-  <*> (AT.hexadecimal >>= limitSize)-  <*  AT.char ':'-  <*> (AT.hexadecimal >>= limitSize)-  <*  AT.char ':'-  <*> (AT.hexadecimal >>= limitSize)-  <*  AT.char ':'-  <*> (AT.hexadecimal >>= limitSize)-  where-  limitSize i =-    if i > 255-      then fail "All octets in a mac address must be between 00 and FF"-      else return i--bytestringParser :: AB.Parser Mac-bytestringParser = fromOctets'-  <$> (AB.hexadecimal >>= limitSize)-  <*  AB.char ':'-  <*> (AB.hexadecimal >>= limitSize)-  <*  AB.char ':'-  <*> (AB.hexadecimal >>= limitSize)-  <*  AB.char ':'-  <*> (AB.hexadecimal >>= limitSize)-  <*  AB.char ':'-  <*> (AB.hexadecimal >>= limitSize)-  <*  AB.char ':'-  <*> (AB.hexadecimal >>= limitSize)-  where-  limitSize i =-    if i > 255-      then fail "All octets in a mac address must be between 00 and FF"-      else return i- fromOctets :: Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac-fromOctets a b c d e f = fromOctets'+fromOctets a b c d e f = fromOctetsNoCast   (fromIntegral a) (fromIntegral b) (fromIntegral c)   (fromIntegral d) (fromIntegral e) (fromIntegral f) -fromOctets' :: Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> Mac-fromOctets' a b c d e f = Mac+fromOctetsNoCast :: Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> Mac+fromOctetsNoCast a b c d e f = Mac     ( shiftL a 8 .|. b )     ( shiftL c 24 .|. shiftL d 16 .|. shiftL e 8 .|. f )+{-# INLINE fromOctetsNoCast #-}  
src/Net/Mac/ByteString/Char8.hs view
@@ -5,7 +5,8 @@   , parser   ) where -import Net.Mac+import Net.Types (Mac(..))+import Net.Mac (fromOctetsNoCast) import Data.ByteString (ByteString) import Data.Attoparsec.ByteString.Char8 (Parser) import Data.ByteString.Lazy.Builder (Builder)@@ -28,7 +29,7 @@ builder = Builder.byteString . encode  parser :: Parser Mac-parser = fromOctets'+parser = fromOctetsNoCast   <$> (AB.hexadecimal >>= limitSize)   <*  AB.char ':'   <*> (AB.hexadecimal >>= limitSize)
src/Net/Mac/Text.hs view
@@ -6,24 +6,25 @@   , parser   ) where -import Net.Mac+import Net.Types (Mac(..))+import Net.Mac (fromOctetsNoCast) import Data.Text (Text)-import Net.Internal (rightToMaybe)+import qualified Net.Internal as Internal import qualified Data.Attoparsec.Text as AT import qualified Data.Text.Lazy.Builder as TBuilder  encode :: Mac -> Text-encode = toText+encode (Mac a b) = Internal.macToText a b  decodeEither :: Text -> Either String Mac-decodeEither = fromText'+decodeEither = Internal.macFromText' fromOctetsNoCast  decode :: Text -> Maybe Mac-decode = rightToMaybe . decodeEither+decode = Internal.rightToMaybe . decodeEither  builder :: Mac -> TBuilder.Builder-builder = toTextBuilder+builder (Mac a b) = Internal.macToTextBuilder a b  parser :: AT.Parser Mac-parser = textParser+parser = Internal.macTextParser fromOctetsNoCast 
src/Net/Types.hs view
@@ -1,15 +1,30 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UnboxedTuples #-}+ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}  module Net.Types   ( IPv4(..)   , IPv4Range(..)+  , Mac(..)   ) where  import qualified Net.Internal         as Internal import qualified Data.Aeson           as Aeson import qualified Data.Aeson.Types     as Aeson import qualified Data.Attoparsec.Text as AT+import qualified Data.Vector.Generic            as GVector+import qualified Data.Vector.Unboxed            as UVector+import qualified Data.Vector.Primitive          as PVector+import qualified Data.Vector.Generic.Mutable    as MGVector+import qualified Data.Vector.Unboxed.Mutable    as MUVector+import qualified Data.Vector.Primitive.Mutable  as MPVector+import Data.Primitive.Types (Prim)+import Data.Bits ((.|.),shiftL) import Data.Coerce (coerce) import Control.Monad import Data.Word@@ -20,7 +35,7 @@  -- | A 32-bit Internet Protocol address. newtype IPv4 = IPv4 { getIPv4 :: Word32 }-  deriving (Eq,Ord,Show,Read,Enum,Bounded,Hashable,Generic)+  deriving (Eq,Ord,Show,Read,Enum,Bounded,Hashable,Generic,Prim)  -- | The length should be between 0 and 32. These bounds are inclusive. --   This expectation is not in any way enforced by this library because@@ -54,27 +69,70 @@ mkIPv4Range w len = IPv4Range (IPv4 w) len {-# INLINE mkIPv4Range #-} --- newtype instance UVector.MVector s IPv4 = MV_IPv4 (UVector.MVector s Word32)------ instance MVector UVector.MVector IPv4 where---   basicLength = coerce (basicLength :: UVector.MVector s Word32 -> Int)---   basicUnsafeSlice = coerce (basicUnsafeSlice :: Int -> Int -> UVector.MVector s Word32 -> UVector.MVector s Word32)---   basicInitialize :: forall m. PrimMonad m => UVector.MVector (PrimState m) IPv4 -> m ()---   basicInitialize = coerce (basicInitialize :: PrimMonad m => UVector.MVector (PrimState m) Word32 -> m ())---   basicUnsafeReplicate :: forall m. PrimMonad m => Int -> IPv4 -> m (UVector.MVector (PrimState m) IPv4)---   basicUnsafeReplicate i (IPv4 w) = fmap coerce (basicUnsafeReplicate i w :: m (UVector.MVector (PrimState m) Word32))---   basicUnsafeRead :: forall m. PrimMonad m => UVector.MVector (PrimState m) IPv4 -> Int -> m IPv4---   basicUnsafeRead v i = fmap coerce (basicUnsafeRead (coerce v :: UVector.MVector (PrimState m) Word32) i :: m Word32)---   basicUnsafeWrite :: forall m. PrimMonad m => UVector.MVector (PrimState m) IPv4 -> Int -> IPv4 -> m ()---   basicUnsafeWrite = coerce (basicUnsafeWrite :: UVector.MVector (PrimState m) Word32 -> Int -> Word32 -> m ())---   basicClear :: forall m. PrimMonad m => UVector.MVector (PrimState m) IPv4 -> m ()---   basicClear = coerce (basicClear :: UVector.MVector (PrimState m) Word32 -> m ())---   basicSet :: forall m. PrimMonad m => UVector.MVector (PrimState m) IPv4 -> IPv4 -> m ()---   basicSet = coerce (basicSet :: UVector.MVector (PrimState m) Word32 -> Word32 -> m ())---   basicUnsafeCopy :: forall m. PrimMonad m => UVector.MVector (PrimState m) IPv4 -> UVector.MVector (PrimState m) IPv4 -> m ()---   basicUnsafeCopy = coerce (basicUnsafeCopy :: UVector.MVector (PrimState m) Word32 -> UVector.MVector (PrimState m) Word32 -> m ())---   basicUnsafeMove :: forall m. PrimMonad m => UVector.MVector (PrimState m) IPv4 -> UVector.MVector (PrimState m) IPv4 -> m ()---   basicUnsafeMove = coerce (basicUnsafeMove :: UVector.MVector (PrimState m) Word32 -> UVector.MVector (PrimState m) Word32 -> m ())---   basicUnsafeGrow :: forall m. PrimMonad m => UVector.MVector (PrimState m) IPv4 -> Int -> m (UVector.MVector (PrimState m) IPv4)---   basicUnsafeGrow (MV_IPv4 v) i = fmap coerce (basicUnsafeGrow v i)+newtype instance UVector.MVector s IPv4 = MV_IPv4 (PVector.MVector s IPv4)+newtype instance UVector.Vector IPv4 = V_IPv4 (PVector.Vector IPv4) +instance UVector.Unbox IPv4++instance MGVector.MVector UVector.MVector IPv4 where+  {-# INLINE basicLength #-}+  {-# INLINE basicUnsafeSlice #-}+  {-# INLINE basicOverlaps #-}+  {-# INLINE basicUnsafeNew #-}+  {-# INLINE basicInitialize #-}+  {-# INLINE basicUnsafeReplicate #-}+  {-# INLINE basicUnsafeRead #-}+  {-# INLINE basicUnsafeWrite #-}+  {-# INLINE basicClear #-}+  {-# INLINE basicSet #-}+  {-# INLINE basicUnsafeCopy #-}+  {-# INLINE basicUnsafeGrow #-}+  basicLength (MV_IPv4 v) = MGVector.basicLength v+  basicUnsafeSlice i n (MV_IPv4 v) = MV_IPv4 $ MGVector.basicUnsafeSlice i n v+  basicOverlaps (MV_IPv4 v1) (MV_IPv4 v2) = MGVector.basicOverlaps v1 v2+  basicUnsafeNew n = MV_IPv4 `liftM` MGVector.basicUnsafeNew n+  basicInitialize (MV_IPv4 v) = MGVector.basicInitialize v+  basicUnsafeReplicate n x = MV_IPv4 `liftM` MGVector.basicUnsafeReplicate n x+  basicUnsafeRead (MV_IPv4 v) i = MGVector.basicUnsafeRead v i+  basicUnsafeWrite (MV_IPv4 v) i x = MGVector.basicUnsafeWrite v i x+  basicClear (MV_IPv4 v) = MGVector.basicClear v+  basicSet (MV_IPv4 v) x = MGVector.basicSet v x+  basicUnsafeCopy (MV_IPv4 v1) (MV_IPv4 v2) = MGVector.basicUnsafeCopy v1 v2+  basicUnsafeMove (MV_IPv4 v1) (MV_IPv4 v2) = MGVector.basicUnsafeMove v1 v2+  basicUnsafeGrow (MV_IPv4 v) n = MV_IPv4 `liftM` MGVector.basicUnsafeGrow v n++instance GVector.Vector UVector.Vector IPv4 where+  {-# INLINE basicUnsafeFreeze #-}+  {-# INLINE basicUnsafeThaw #-}+  {-# INLINE basicLength #-}+  {-# INLINE basicUnsafeSlice #-}+  {-# INLINE basicUnsafeIndexM #-}+  {-# INLINE elemseq #-}+  basicUnsafeFreeze (MV_IPv4 v) = V_IPv4 `liftM` GVector.basicUnsafeFreeze v+  basicUnsafeThaw (V_IPv4 v) = MV_IPv4 `liftM` GVector.basicUnsafeThaw v+  basicLength (V_IPv4 v) = GVector.basicLength v+  basicUnsafeSlice i n (V_IPv4 v) = V_IPv4 $ GVector.basicUnsafeSlice i n v+  basicUnsafeIndexM (V_IPv4 v) i = GVector.basicUnsafeIndexM v i+  basicUnsafeCopy (MV_IPv4 mv) (V_IPv4 v) = GVector.basicUnsafeCopy mv v+  elemseq _ = seq++data Mac = Mac+  { macA :: {-# UNPACK #-} !Word16+  , macB :: {-# UNPACK #-} !Word32+  }+  deriving (Eq,Ord,Show,Read,Generic)++instance Hashable Mac++instance ToJSON Mac where+  toJSON (Mac a b) = Aeson.String (Internal.macToText a b)++instance FromJSON Mac where+  parseJSON = Internal.attoparsecParseJSON+    (Internal.macTextParser macFromOctets' <* AT.endOfInput)++macFromOctets' :: Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> Mac+macFromOctets' a b c d e f = Mac+    ( shiftL a 8 .|. b )+    ( shiftL c 24 .|. shiftL d 16 .|. shiftL e 8 .|. f )+{-# INLINE macFromOctets' #-}