X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2FIPv4Address.hs;h=dac7ddaf0596e9fba46b077d4321e88149d23b88;hb=d32fe2f0a6c83ba3046a405eda40f83c794c000d;hp=6d1e56ec38becf939b0ceede6c0262fb0a2beee6;hpb=4b16a47bd77a82d63072497514476faeba6b8e83;p=hath.git diff --git a/src/IPv4Address.hs b/src/IPv4Address.hs index 6d1e56e..dac7dda 100644 --- a/src/IPv4Address.hs +++ b/src/IPv4Address.hs @@ -1,140 +1,186 @@ module IPv4Address -( ipv4address_from_octets, - ipv4address_tests, - IPv4Address(None), +( ipv4address_tests, + IPv4Address(..), max_address, min_address, most_sig_bit_different, - octet1, - octet2, - octet3, - octet4 ) where -import Test.HUnit -import Test.QuickCheck +import Data.Maybe (fromJust) +import Test.HUnit (assertEqual) +import Test.Framework (Test, testGroup) +import Test.Framework.Providers.HUnit (testCase) +import Test.QuickCheck (Arbitrary(..), Gen) import Maskable import Maskbits import Octet -data IPv4Address = None | IPv4Address { octet1 :: Octet, - octet2 :: Octet, - octet3 :: Octet, - octet4 :: Octet } - deriving (Eq) +data IPv4Address = + IPv4Address { octet1 :: Octet, + octet2 :: Octet, + octet3 :: Octet, + octet4 :: Octet } + deriving (Eq) instance Show IPv4Address where - show IPv4Address.None = "None" - show addr = concat [(show oct1) ++ ".", - (show oct2) ++ ".", - (show oct3) ++ ".", - (show oct4)] - where - oct1 = (octet1 addr) - oct2 = (octet2 addr) - oct3 = (octet3 addr) - oct4 = (octet4 addr) + show addr = concat [(show oct1) ++ ".", + (show oct2) ++ ".", + (show oct3) ++ ".", + (show oct4)] + where + oct1 = (octet1 addr) + oct2 = (octet2 addr) + oct3 = (octet3 addr) + oct4 = (octet4 addr) instance Arbitrary IPv4Address where - arbitrary = do - oct1 <- arbitrary :: Gen Octet - oct2 <- arbitrary :: Gen Octet - oct3 <- arbitrary :: Gen Octet - oct4 <- arbitrary :: Gen Octet - return (IPv4Address oct1 oct2 oct3 oct4) - - coarbitrary _ = variant 0 + arbitrary = do + oct1 <- arbitrary :: Gen Octet + oct2 <- arbitrary :: Gen Octet + oct3 <- arbitrary :: Gen Octet + oct4 <- arbitrary :: Gen Octet + return (IPv4Address oct1 oct2 oct3 oct4) instance Maskable IPv4Address where - apply_mask _ Maskbits.None _ = IPv4Address.None - apply_mask addr mask bit - | mask == ThirtyTwo = addr - | mask == ThirtyOne = addr { octet4 = (apply_mask oct4 Seven bit) } - | mask == Thirty = addr { octet4 = (apply_mask oct4 Six bit) } - | mask == TwentyNine = addr { octet4 = (apply_mask oct4 Five bit) } - | mask == TwentyEight = addr { octet4 = (apply_mask oct4 Four bit) } - | mask == TwentySeven = addr { octet4 = (apply_mask oct4 Three bit) } - | mask == TwentySix = addr { octet4 = (apply_mask oct4 Two bit) } - | mask == TwentyFive = addr { octet4 = (apply_mask oct4 One bit) } - | mask == TwentyFour = addr { octet4 = min_octet } - | mask == TwentyThree = addr { octet3 = (apply_mask oct3 Seven bit), - octet4 = min_octet } - | mask == TwentyTwo = addr { octet3 = (apply_mask oct3 Six bit), - octet4 = min_octet } - | mask == TwentyOne = addr { octet3 = (apply_mask oct3 Five bit), - octet4 = min_octet } - | mask == Twenty = addr { octet3 = (apply_mask oct3 Four bit), - octet4 = min_octet } - | mask == Nineteen = addr { octet3 = (apply_mask oct3 Three bit), - octet4 = min_octet } - | mask == Eighteen = addr { octet3 = (apply_mask oct3 Two bit), - octet4 = min_octet } - | mask == Seventeen = addr { octet3 = (apply_mask oct3 One bit), - octet4 = min_octet } - | mask == Sixteen = addr { octet3 = min_octet, - octet4 = min_octet } - | mask == Fifteen = min_address { octet1 = oct1, - octet2 = (apply_mask oct2 Seven bit) } - | mask == Fourteen = min_address { octet1 = oct1, - octet2 = (apply_mask oct2 Six bit) } - | mask == Thirteen = min_address { octet1 = oct1, - octet2 = (apply_mask oct2 Five bit) } - | mask == Twelve = min_address { octet1 = oct1, - octet2 = (apply_mask oct2 Four bit) } - | mask == Eleven = min_address { octet1 = oct1, - octet2 = (apply_mask oct2 Three bit) } - | mask == Ten = min_address { octet1 = oct1, - octet2 = (apply_mask oct2 Two bit) } - | mask == Nine = min_address { octet1 = oct1, - octet2 = (apply_mask oct2 One bit) } - | mask == Eight = min_address { octet1 = oct1 } - | mask == Seven = min_address { octet1 = (apply_mask oct1 Seven bit) } - | mask == Six = min_address { octet1 = (apply_mask oct1 Six bit) } - | mask == Five = min_address { octet1 = (apply_mask oct1 Five bit) } - | mask == Four = min_address { octet1 = (apply_mask oct1 Four bit) } - | mask == Three = min_address { octet1 = (apply_mask oct1 Three bit) } - | mask == Two = min_address { octet1 = (apply_mask oct1 Two bit) } - | mask == One = min_address { octet1 = (apply_mask oct1 One bit) } - | mask == Zero = min_address - | otherwise = IPv4Address.None - where - oct1 = (octet1 addr) - oct2 = (octet2 addr) - oct3 = (octet3 addr) - oct4 = (octet4 addr) - - --- We don't export our constructor so this function is the only --- way to construct an address from octets. As a result, we can --- return IPv4Address.None in response to being passed one of more --- Octet.None octets. -ipv4address_from_octets :: Octet -> Octet -> Octet -> Octet -> IPv4Address -ipv4address_from_octets oct1 oct2 oct3 oct4 - | or [oct1 == Octet.None, - oct2 == Octet.None, - oct3 == Octet.None, - oct4 == Octet.None] = IPv4Address.None - | otherwise = IPv4Address oct1 oct2 oct3 oct4 - - --- The minimum possible IPv4 address, 0.0.0.0. + + apply_mask addr mask bit = + apply_mask' mask + where + oct1 = octet1 addr + oct2 = octet2 addr + oct3 = octet3 addr + oct4 = octet4 addr + + -- A copy of 'addr' with the fourth octet zeroed (or oned). + new_addr1 = addr { octet4 = (apply_mask oct4 Zero bit) } + + -- Likewise for new_addr1's third octet. + new_addr2 = new_addr1 { octet3 = (apply_mask oct3 Zero bit) } + + -- And new_addr2's second octet. + new_addr3 = new_addr2 { octet2 = (apply_mask oct2 Zero bit) } + + -- This helper function allows us to pattern-match cleanly. + apply_mask' :: Maskbits -> IPv4Address + + apply_mask' ThirtyTwo = addr + + apply_mask' ThirtyOne = addr { octet4 = (apply_mask oct4 Seven bit) } + + apply_mask' Thirty = + addr { octet4 = (apply_mask oct4 Six bit) } + + apply_mask' TwentyNine = + addr { octet4 = (apply_mask oct4 Five bit) } + + apply_mask' TwentyEight = + addr { octet4 = (apply_mask oct4 Four bit) } + + apply_mask' TwentySeven = + addr { octet4 = (apply_mask oct4 Three bit) } + + apply_mask' TwentySix = + addr { octet4 = (apply_mask oct4 Two bit) } + + apply_mask' TwentyFive = + addr { octet4 = (apply_mask oct4 One bit) } + + apply_mask' TwentyFour = new_addr1 + + apply_mask' TwentyThree = + new_addr1 { octet3 = (apply_mask oct3 Seven bit) } + + apply_mask' TwentyTwo = + new_addr1 { octet3 = (apply_mask oct3 Six bit) } + + apply_mask' TwentyOne = + new_addr1 { octet3 = (apply_mask oct3 Five bit) } + + apply_mask' Twenty = + new_addr1 { octet3 = (apply_mask oct3 Four bit) } + + apply_mask' Nineteen = + new_addr1 { octet3 = (apply_mask oct3 Three bit) } + + apply_mask' Eighteen = + new_addr1 { octet3 = (apply_mask oct3 Two bit) } + + apply_mask' Seventeen = + new_addr1 { octet3 = (apply_mask oct3 One bit) } + + apply_mask' Sixteen = + new_addr2 + + apply_mask' Fifteen = + new_addr2 { octet2 = (apply_mask oct2 Seven bit) } + + apply_mask' Fourteen = + new_addr2 { octet2 = (apply_mask oct2 Six bit) } + + apply_mask' Thirteen = + new_addr2 { octet2 = (apply_mask oct2 Five bit) } + + apply_mask' Twelve = + new_addr2 { octet2 = (apply_mask oct2 Four bit) } + + apply_mask' Eleven = + new_addr2 { octet2 = (apply_mask oct2 Three bit) } + + apply_mask' Ten = + new_addr2 { octet2 = (apply_mask oct2 Two bit) } + + apply_mask' Nine = + new_addr2 { octet2 = (apply_mask oct2 One bit) } + + apply_mask' Eight = + new_addr3 { octet2 = (apply_mask oct2 Zero bit) } + + apply_mask' Seven = + new_addr3 { octet1 = (apply_mask oct1 Seven bit) } + + apply_mask' Six = + new_addr3 { octet1 = (apply_mask oct1 Six bit) } + + apply_mask' Five = + new_addr3 { octet1 = (apply_mask oct1 Five bit) } + + apply_mask' Four = + new_addr3 { octet1 = (apply_mask oct1 Four bit) } + + apply_mask' Three = + new_addr3 { octet1 = (apply_mask oct1 Three bit) } + + apply_mask' Two = + new_addr3 { octet1 = (apply_mask oct1 Two bit) } + + apply_mask' One = + new_addr3 { octet1 = (apply_mask oct1 One bit) } + + apply_mask' Zero = + new_addr3 { octet1 = (apply_mask oct1 Zero bit) } + + + +-- | The minimum possible IPv4 address, 0.0.0.0. min_address :: IPv4Address -min_address = IPv4Address min_octet min_octet min_octet min_octet +min_address = + IPv4Address min_octet min_octet min_octet min_octet --- The maximum possible IPv4 address, 255.255.255.255. +-- | The maximum possible IPv4 address, 255.255.255.255. max_address :: IPv4Address -max_address = IPv4Address max_octet max_octet max_octet max_octet +max_address = + IPv4Address max_octet max_octet max_octet max_octet --- Given two addresses, find the number of the most significant bit --- where they differ. If the addresses are the same, return --- Maskbits.Zero. +-- | Given two addresses, find the number of the most significant bit +-- where they differ. If the addresses are the same, return +-- Maskbits.Zero. most_sig_bit_different :: IPv4Address -> IPv4Address -> Maskbits most_sig_bit_different addr1 addr2 | addr1 == addr2 = Maskbits.Zero @@ -250,24 +296,41 @@ most_sig_bit_different addr1 addr2 -- HUnit Tests mk_testaddr :: Int -> Int -> Int -> Int -> IPv4Address mk_testaddr a b c d = - IPv4Address oct1 oct2 oct3 oct4 - where - oct1 = octet_from_int a - oct2 = octet_from_int b - oct3 = octet_from_int c - oct4 = octet_from_int d + IPv4Address oct1 oct2 oct3 oct4 + where + oct1 = fromJust $ octet_from_int a + oct2 = fromJust $ octet_from_int b + oct3 = fromJust $ octet_from_int c + oct4 = fromJust $ octet_from_int d test_most_sig_bit_different1 :: Test test_most_sig_bit_different1 = - TestCase $ assertEqual "10.1.1.0 and 10.1.0.0 differ in bit 24" TwentyFour (most_sig_bit_different (mk_testaddr 10 1 1 0) (mk_testaddr 10 1 0 0)) + testCase desc $ assertEqual desc + TwentyFour + bit + where + desc = "10.1.1.0 and 10.1.0.0 differ in bit 24" + addr1 = mk_testaddr 10 1 1 0 + addr2 = (mk_testaddr 10 1 0 0) + bit = most_sig_bit_different addr1 addr2 + test_most_sig_bit_different2 :: Test test_most_sig_bit_different2 = - TestCase $ assertEqual "10.1.2.0 and 10.1.1.0 differ in bit 23" TwentyThree (most_sig_bit_different (mk_testaddr 10 1 2 0) (mk_testaddr 10 1 1 0)) + testCase desc $ assertEqual desc + TwentyThree + bit + where + desc = "10.1.2.0 and 10.1.1.0 differ in bit 23" + addr1 = mk_testaddr 10 1 2 0 + addr2 = mk_testaddr 10 1 1 0 + bit = most_sig_bit_different addr1 addr2 -ipv4address_tests :: [Test] -ipv4address_tests = [ test_most_sig_bit_different1, - test_most_sig_bit_different2 ] +ipv4address_tests :: Test +ipv4address_tests = + testGroup "IPv4 Address Tests" [ + test_most_sig_bit_different1, + test_most_sig_bit_different2 ]