packages feed

IPv6Addr 0.6.0.2 → 0.6.1.0

raw patch · 8 files changed

+101/−140 lines, 8 filesdep ~attoparsecdep ~basedep ~iproutePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: attoparsec, base, iproute, network, network-info, random, text

API changes (from Hackage documentation)

- Text.IPv6Addr: instance Eq IPv6Addr
- Text.IPv6Addr.Types: instance Eq IPv6AddrToken
- Text.IPv6Addr.Types: instance Show IPv6Addr
- Text.IPv6Addr.Types: instance Show IPv6AddrToken
+ Text.IPv6Addr: instance GHC.Classes.Eq Text.IPv6Addr.Types.IPv6Addr
+ Text.IPv6Addr: toUNC :: IPv6Addr -> Text
+ Text.IPv6Addr.Types: instance GHC.Classes.Eq Text.IPv6Addr.Types.IPv6AddrToken
+ Text.IPv6Addr.Types: instance GHC.Show.Show Text.IPv6Addr.Types.IPv6Addr
+ Text.IPv6Addr.Types: instance GHC.Show.Show Text.IPv6Addr.Types.IPv6AddrToken

Files

IPv6Addr.cabal view
@@ -1,5 +1,5 @@ name:                IPv6Addr-version:             0.6.0.2+version:             0.6.1.0 synopsis:            Library to deal with IPv6 address text representations. description:         Library to deal with IPv6 address text representations, canonization and manipulations. homepage:            https://github.com/MichelBoucey/IPv6Addr@@ -7,7 +7,7 @@ license-file:        LICENSE author:              Michel Boucey maintainer:          michel.boucey@gmail.com-copyright:           Copyright © 2011-2015 - Michel Boucey+copyright:           Copyright (c) 2011-2015 - Michel Boucey category:            Network build-type:          Simple extra-source-files:  README.md@@ -22,6 +22,7 @@   other-extensions:    OverloadedStrings   build-depends:       base >=4.6 && <5, text >=1.1, iproute >=1.3, network >=2.5, random >=1.0, attoparsec >=0.12, network-info >=0.2   default-language:    Haskell2010+  GHC-Options:         -Wall  Test-Suite tests   Type:           exitcode-stdio-1.0@@ -34,3 +35,4 @@                   test-framework,                   test-framework-hunit,                   text+
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2011-2015, Michel Boucey+Copyright (c) 2011-2016, Michel Boucey All rights reserved.  Redistribution and use in source and binary forms, with or without
README.md view
@@ -1,1 +1,1 @@-IPv6Addr is a Haskell library to Deal with IPv6 address text representations, canonization and manipulations.+IPv6Addr is a Haskell library to deal with IPv6 address text representations, canonization and manipulations.
Text/IPv6Addr.hs view
@@ -1,16 +1,5 @@--- --------------------------------------------------------------------------------- Module      :  Text.IPv6Addr--- Copyright   :  Copyright © Michel Boucey 2011-2015--- License     :  BSD-style--- Maintainer  :  michel.boucey@gmail.com------ Dealing with IPv6 address text representations, canonization and manipulations.------- ------------------------------------------------------------------------------ {-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}  module Text.IPv6Addr     (@@ -25,23 +14,22 @@     , toHostName     -- * Utils     , toIP6ARPA+    , toUNC     , getIPv6AddrOf     , randIPv6Addr     , randIPv6AddrWithPrefix     ) where --- import Control.Applicative (pure,(<$>),(<*>))-import Control.Applicative (pure,(<$>))-import Data.IP (IPv6)-import Data.Maybe (fromJust,isNothing)-import Data.Monoid ((<>))-import qualified Data.Text as T-import Network (HostName)-import System.Random (randomRIO)+import           Data.IP                (IPv6)+import           Data.Maybe             (fromJust, isNothing)+import           Data.Monoid            ((<>))+import qualified Data.Text              as T+import           Network                (HostName)+import           System.Random          (randomRIO) -import Text.IPv6Addr.Internal-import Text.IPv6Addr.Manip (randIPv6AddrChunk,randPartialIPv6Addr)-import Text.IPv6Addr.Types+import           Text.IPv6Addr.Internal+import           Text.IPv6Addr.Manip    (randPartialIPv6Addr)+import           Text.IPv6Addr.Types  instance Eq IPv6Addr where     (==) (IPv6Addr a) (IPv6Addr b) = show (maybePureIPv6Addr a) == show (maybePureIPv6Addr b)@@ -88,6 +76,17 @@     trans ':' = T.empty     trans c   = "." <> T.pack [c] +-- | Returns the Windows UNC path name of the given IPv6 Address.+--+-- > toUNC (IPv6Addr "2001:0DB8:002a:1005:230:48ff:fe73:989d") == "2001-db8-2a-1005-230-48ff-fe73-989d.ipv6-literal.net"+--+toUNC :: IPv6Addr -> T.Text+toUNC a =+    (T.concatMap trans $ fromIPv6Addr $ fromJust $ maybePureIPv6Addr $ fromIPv6Addr a) <> ".ipv6-literal.net"+  where+    trans ':' = "-"+    trans c   = T.pack [c]+ -- | Given an 'IPv6Addr', returns the corresponding 'HostName'. toHostName :: IPv6Addr -> HostName toHostName = show@@ -136,9 +135,9 @@                                           ]             return $ ipv6TokensToIPv6Addr tks         else case maybeIPv6AddrTokens (fromJust p) of-            Just tks -> do +            Just tks -> do                 ntks <- do let ctks = countChunks tks-                           case snd ctks of+                           case (snd ctks :: Int) of                                0 -> return $ 8 - fst ctks                                1 -> return $ 6 - fst ctks                                _ -> return 0@@ -166,4 +165,5 @@         case last ts of             SixteenBit _ -> ts ++ [Colon]             AllZeros     -> ts ++ [Colon]-            _            -> ts +            _            -> ts+
Text/IPv6Addr/Internal.hs view
@@ -1,16 +1,3 @@--- --------------------------------------------------------------------------------- | --- Module      :  Text.IPv6Addr--- Copyright   :  Copyright © Michel Boucey 2011-2015--- License     :  BSD-Style--- Maintainer  :  michel.boucey@gmail.com------ Dealing with IPv6 address text representations, canonization and manipulations.------- ------------------------------------------------------------------------------ {-# LANGUAGE OverloadedStrings #-}  module Text.IPv6Addr.Internal@@ -29,21 +16,19 @@     , networkInterfacesIPv6AddrList     ) where -import Control.Monad (replicateM)-import Data.Attoparsec.Text-import Data.Char (isDigit,isHexDigit,toLower)-import Data.Monoid ((<>))-import Control.Applicative ((<|>),(<*))-import Data.List (group,isSuffixOf,elemIndex,elemIndices,intersperse)-import Numeric (showHex)-import qualified Data.Text as T-import qualified Data.Text.Read as R (decimal)-import Data.Maybe (fromJust)-import Network.Info--import Text.IPv6Addr.Types+import           Control.Applicative  ((<|>))+import           Data.Attoparsec.Text+import           Data.Char            (isDigit)+import           Data.List            (elemIndex, elemIndices, group,+                                       intersperse, isSuffixOf)+import           Data.Maybe           (fromJust)+import           Data.Monoid          ((<>))+import qualified Data.Text            as T+import qualified Data.Text.Read       as R (decimal)+import           Network.Info+import           Numeric              (showHex) -tok0 = "0"+import           Text.IPv6Addr.Types  -- | Returns the 'T.Text' of an IPv6 address. fromIPv6Addr :: IPv6Addr -> T.Text@@ -55,25 +40,25 @@  -- | Returns the corresponding 'T.Text' of an IPv6 address token. ipv6TokenToText :: IPv6AddrToken -> T.Text-ipv6TokenToText (SixteenBit s) = s +ipv6TokenToText (SixteenBit s) = s ipv6TokenToText Colon = ":" ipv6TokenToText DoubleColon = "::"-ipv6TokenToText AllZeros = tok0 -- "A single 16-bit 0000 field MUST be represented as 0" (RFC 5952, 4.1)+ipv6TokenToText AllZeros = "0" -- "A single 16-bit 0000 field MUST be represented as 0" (RFC 5952, 4.1) ipv6TokenToText (IPv4Addr a) = a  -- | Returns 'True' if a list of 'IPv6AddrToken' constitutes a valid IPv6 Address. isIPv6Addr :: [IPv6AddrToken] -> Bool isIPv6Addr [] = False isIPv6Addr [DoubleColon] = True-isIPv6Addr [DoubleColon,SixteenBit tok1] = True+isIPv6Addr [DoubleColon,SixteenBit "1"] = True isIPv6Addr tks =     diffNext tks && (do         let cdctks = countDoubleColon tks-        let lentks = length tks-        let lasttk = last tks-        let lenconst = (lentks == 15 && cdctks == 0) || (lentks < 15 && cdctks == 1)+            lentks = length tks+            lasttk = last tks+            lenconst = (lentks == 15 && cdctks == 0) || (lentks < 15 && cdctks == 1)         firstValidToken tks &&-            (case countIPv4Addr tks of+            (case countIPv4Addr tks :: Int of                 0 -> case lasttk of                          SixteenBit _ -> lenconst                          DoubleColon  -> lenconst@@ -82,7 +67,7 @@                 1 -> case lasttk of                          IPv4Addr _ -> (lentks == 13 && cdctks == 0) || (lentks < 12 && cdctks == 1)                          _          -> False-                otherwise -> False))+                _ -> False))           where diffNext [] = False                 diffNext [_] = True                 diffNext (t:ts) = do@@ -97,26 +82,28 @@                                             AllZeros     -> False                                             _            -> diffNext ts                         _            -> diffNext ts-                firstValidToken l = +                firstValidToken l =                     case head l of                         SixteenBit _ -> True                         DoubleColon  -> True                         AllZeros     -> True                         _            -> False                 countDoubleColon l = length $ elemIndices DoubleColon l-                tok1 = "1" -countIPv4Addr = foldr oneMoreIPv4Addr 0+countIPv4Addr :: [IPv6AddrToken] -> Int+countIPv4Addr =+    foldr oneMoreIPv4Addr 0   where-    oneMoreIPv4Addr t c = case t of-                              IPv4Addr _ -> c + 1-                              otherwise  -> c+    oneMoreIPv4Addr t c =+      case t of+          IPv4Addr _ -> c + 1+          _          -> c  -- | This is the main function which returns 'Just' the list of a tokenized IPv6 -- address text representation validated against RFC 4291 and canonized -- in conformation with RFC 5952, or 'Nothing'. maybeTokIPv6Addr :: T.Text -> Maybe [IPv6AddrToken]-maybeTokIPv6Addr t = +maybeTokIPv6Addr t =     case maybeIPv6AddrTokens t of         Just ltks -> if isIPv6Addr ltks                          then Just $ (ipv4AddrReplacement . toDoubleColon . fromDoubleColon) ltks@@ -141,12 +128,13 @@  -- | Tokenize a 'T.Text' into 'Just' a list of 'IPv6AddrToken', or 'Nothing'. maybeIPv6AddrTokens :: T.Text -> Maybe [IPv6AddrToken]-maybeIPv6AddrTokens s = +maybeIPv6AddrTokens s =     case readText s of          Done r l -> if r==T.empty then Just l else Nothing          Fail {}  -> Nothing+         Partial _ -> Nothing   where-    readText s = feed (parse (many1 $ ipv4Addr <|> sixteenBit <|> doubleColon <|> colon) s) T.empty+    readText _s = feed (parse (many1 $ ipv4Addr <|> sixteenBit <|> doubleColon <|> colon) _s) T.empty  -- | An embedded IPv4 address have to be rewritten to output a pure IPv6 Address -- text representation in hexadecimal digits. But some well-known prefixed IPv6@@ -195,7 +183,7 @@         _          -> [t]       where         toHex a = map (\x -> T.pack $ showHex (read (T.unpack x)::Int) "") $ T.split (=='.') a-        addZero d = if T.length d == 1 then tok0 <> d else d+        addZero d = if T.length d == 1 then "0" <> d else d  expandTokens :: [IPv6AddrToken] -> [IPv6AddrToken] expandTokens = map expandToken@@ -204,21 +192,21 @@         expandToken t = t  fromDoubleColon :: [IPv6AddrToken] -> [IPv6AddrToken]-fromDoubleColon tks = +fromDoubleColon tks =     if DoubleColon `notElem` tks         then tks         else do let s = splitAt (fromJust $ elemIndex DoubleColon tks) tks-                let fsts = fst s-                let snds = if not (null (snd s)) then tail(snd s) else []-                let fste = if null fsts then [] else fsts ++ [Colon]-                let snde = if null snds then [] else Colon : snds+                    fsts = fst s+                    snds = if not (null (snd s)) then tail(snd s) else []+                    fste = if null fsts then [] else fsts ++ [Colon]+                    snde = if null snds then [] else Colon : snds                 fste ++ allZerosTokensReplacement(quantityOfAllZerosTokenToReplace tks) ++ snde       where         allZerosTokensReplacement x = intersperse Colon (replicate x AllZeros)-        quantityOfAllZerosTokenToReplace x =-            ntks tks - foldl (\c x -> if (x /= DoubleColon) && (x /= Colon) then c+1 else c) 0 x+        quantityOfAllZerosTokenToReplace _x =+            ntks tks - foldl (\c _x -> if (_x /= DoubleColon) && (_x /= Colon) then c+1 else c) 0 _x           where-            ntks tks = if countIPv4Addr tks == 1 then 7 else 8+            ntks _tks = if countIPv4Addr _tks == 1 then 7 else 8  toDoubleColon :: [IPv6AddrToken] -> [IPv6AddrToken] toDoubleColon tks =@@ -239,7 +227,7 @@         firstLongestZerosRunIndex x y = sum . snd . unzip $ Prelude.takeWhile (/=(True,y)) x         longestLengthZerosRun x =             maximum $ map longest x-          where longest t = case t of+          where longest _t = case _t of                                 (True,i)  -> i                                 _         -> 0     zerosRunsList x = map helper $ groupZerosRuns x@@ -256,12 +244,6 @@   where     networkInterfacesIPv6Addr (NetworkInterface n _ a _) = (n,a) -fullSixteenBit :: T.Text -> Maybe IPv6AddrToken-fullSixteenBit t =-    case parse ipv6AddrFullChunk t of-        Done a b  -> if a==T.empty then Just $ SixteenBit $ T.pack b else Nothing-        _         -> Nothing- macAddr :: Parser (Maybe [IPv6AddrToken]) macAddr = do     n1 <- count 2 hexaChar <* ":"@@ -293,26 +275,26 @@                                 then do n4 <- manyDigits                                         if n4 /= T.empty                                             then return $ IPv4Addr $ T.intercalate "." [n1,n2,n3,n4]-                                            else parserFailure  -                                else parserFailure  -                    else parserFailure  -        else parserFailure  +                                            else parserFailure+                                else parserFailure+                    else parserFailure+        else parserFailure   where     parserFailure = fail "ipv4Addr parsing failure"     manyDigits = do       ds <- takeWhile1 isDigit-      case R.decimal ds of+      case R.decimal ds :: Either String (Integer, T.Text) of           Right (n,_) -> return (if n < 256 then T.pack $ show n else T.empty)           Left  _     -> return T.empty  doubleColon :: Parser IPv6AddrToken doubleColon = do-    string "::"+    _ <- string "::"     return DoubleColon  colon :: Parser IPv6AddrToken colon = do-    string ":"+    _ <- string ":"     return Colon  ipv6AddrFullChunk :: Parser String@@ -320,3 +302,4 @@  hexaChar :: Parser Char hexaChar = satisfy (inClass "0-9a-fA-F")+
Text/IPv6Addr/Manip.hs view
@@ -1,16 +1,3 @@--- --------------------------------------------------------------------------------- |--- Module      :  Text.IPv6Addr--- Copyright   :  Copyright © Michel Boucey 2011-2015--- License     :  BSD-Style--- Maintainer  :  michel.boucey@gmail.com------ Dealing with IPv6 address text representations, canonization and manipulations.------- ------------------------------------------------------------------------------ module Text.IPv6Addr.Manip     ( randIPv6AddrChunk     , randPartialIPv6Addr@@ -19,24 +6,22 @@     , getTokMacAddrOf     ) where -import Control.Applicative ((<$>))-import Control.Monad (replicateM)-import Data.Attoparsec.Text as A-import Data.Char (intToDigit,isHexDigit)-import Data.List (intersperse)-import Data.Maybe (fromJust)-import qualified Data.Text as T-import Network.Info-import System.Random (randomRIO)+import           Control.Monad          (replicateM)+import           Data.Attoparsec.Text   as A+import           Data.Char              (intToDigit)+import           Data.List              (intersperse)+import qualified Data.Text              as T+import           Network.Info+import           System.Random          (randomRIO) -import Text.IPv6Addr.Internal-import Text.IPv6Addr.Types+import           Text.IPv6Addr.Internal+import           Text.IPv6Addr.Types  -- | Returns 'Just' a random 'SixteenBit' token based on a mask \"____\", each -- underscore being replaced by a random hexadecimal digit. -- -- > randIPv6AddrChunk "_f__" == Just (SixteenBit "bfd4")--- +-- randIPv6AddrChunk :: String -> IO IPv6AddrToken randIPv6AddrChunk m =     mapM getHex m >>= \g -> return $ SixteenBit $ T.dropWhile (=='0') $ T.pack g@@ -51,9 +36,9 @@     | n > 0 && n < 9 = intersperse Colon <$> replicateM n (randIPv6AddrChunk "____")     | otherwise      = return [] --- | Given a MAC address, returns the corresponding 'IPv6AddrToken' list, or an empty list.+-- | Given a MAC address, returns 'Just' the corresponding 'IPv6AddrToken' list, or 'Nothing'. ----- > macAddrToIPv6AddrTokens "fa:1d:58:cc:95:16" == [SixteenBit "fa1d",Colon,SixteenBit "58cc",Colon,SixteenBit "9516"]+-- > macAddrToIPv6AddrTokens "fa:1d:58:cc:95:16" == Just [SixteenBit "fa1d",Colon,SixteenBit "58cc",Colon,SixteenBit "9516"] -- macAddrToIPv6AddrTokens :: T.Text -> Maybe [IPv6AddrToken] macAddrToIPv6AddrTokens t =@@ -82,5 +67,6 @@ getTokMacAddrOf s =     maybe Nothing (macAddrToIPv6AddrTokens . T.pack . show) <$> (lookup s <$> networkInterfacesMacAddrList)   where-    networkInterfacesMacAddrList = getNetworkInterfaces >>= \n -> return $ map networkInterfacesMac n +    networkInterfacesMacAddrList = getNetworkInterfaces >>= \n -> return $ map networkInterfacesMac n       where networkInterfacesMac (NetworkInterface n _ _ m) = (n,m)+
Text/IPv6Addr/Types.hs view
@@ -1,16 +1,3 @@--- --------------------------------------------------------------------------------- |--- Module      :  Text.IPv6Addr--- Copyright   :  Copyright © Michel Boucey 2011-2015--- License     :  BSD-Style--- Maintainer  :  michel.boucey@gmail.com------ Dealing with IPv6 address text representations, canonization and manipulations.------- ------------------------------------------------------------------------------ module Text.IPv6Addr.Types where  import qualified Data.Text as T@@ -27,3 +14,4 @@     | DoubleColon        -- ^ A double-colon stands for a unique compression of many consecutive 16-Bit chunks     | IPv4Addr T.Text    -- ^ An embedded IPv4 address as representation of the last 32-Bit     deriving (Eq,Show)+
tests/Main.hs view
@@ -2,16 +2,16 @@  module Main where  -import Data.Maybe-import Data.Text import Test.Framework import Test.Framework.Providers.HUnit import Test.HUnit  import Text.IPv6Addr +main :: IO () main = defaultMain $ hUnitTestToTests tests +tests :: Test.HUnit.Test tests = TestList   [ (~?=) (maybeIPv6Addr ":") Nothing   , (~?=) (maybeIPv6Addr "::") (Just (IPv6Addr "::"))@@ -100,4 +100,6 @@   , (~?=) (toIP6ARPA (IPv6Addr "fdda:5cc1:23:4::1f")) "f.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.4.0.0.0.3.2.0.0.1.c.c.5.a.d.d.f.IP6.ARPA."   , (~?=) (toIP6ARPA (IPv6Addr "2001:db8::")) "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.IP6.ARPA."   , (~?=) (toIP6ARPA (IPv6Addr "4321:0:1:2:3:4:567:89ab")) "b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.IP6.ARPA."+  , (~?=) (toUNC (IPv6Addr "2001:0DB8:002a:1005:230:48ff:FE73:989d")) "2001-db8-2a-1005-230-48ff-fe73-989d.ipv6-literal.net"+  , (~?=) (toUNC (IPv6Addr "2001:0db8:85a3:0000:0000:8a2e:0370:7334")) "2001-db8-85a3--8a2e-370-7334.ipv6-literal.net"   ]