From a5dfa1fd4dde2d79f42c606a56b4aea303d273e8 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 19 Aug 2013 08:24:29 -0400 Subject: [PATCH] Replace cidr_from_string with a Read instance. --- src/Cidr.hs | 103 ++++++++++++++++++++++++++-------------------------- src/Main.hs | 4 +- 2 files changed, 53 insertions(+), 54 deletions(-) diff --git a/src/Cidr.hs b/src/Cidr.hs index d6acdcf..dc2b556 100644 --- a/src/Cidr.hs +++ b/src/Cidr.hs @@ -2,7 +2,6 @@ -- with the CIDR type. module Cidr ( Cidr(..), - cidr_from_string, cidr_properties, cidr_tests, combine_all, @@ -23,7 +22,7 @@ module Cidr import Data.List (nubBy) import Data.List.Split (splitOneOf) -import Data.Maybe (catMaybes, fromJust, mapMaybe) +import Data.Maybe (catMaybes, mapMaybe) import Test.HUnit (assertEqual) import Test.Framework (Test, testGroup) @@ -43,7 +42,6 @@ data Cidr = Cidr { ipv4address :: IPv4Address, maskbits :: Maskbits } - instance Show Cidr where show cidr = (show (ipv4address cidr)) ++ "/" ++ (show (maskbits cidr)) @@ -79,21 +77,22 @@ maskbits_from_cidr_string s -- of its octets (as Ints). octets_from_cidr_string :: String -> [Octet] octets_from_cidr_string s = - mapMaybe readMaybe (take 4 (splitOneOf "./" s)) - - --- | Return Nothing if we can't parse both maskbits and octets from --- the string. -cidr_from_string :: String -> Maybe Cidr -cidr_from_string s = - case (octets_from_cidr_string s) of - [oct1, oct2, oct3, oct4] -> - case (maskbits_from_cidr_string s) of - Just mbits -> - Just $ Cidr (IPv4Address oct1 oct2 oct3 oct4) mbits - _ -> Nothing - _ -> Nothing + case parts of + (p1:p2:p3:p4:_) -> mapMaybe readMaybe [p1,p2,p3,p4] + _ -> [] + where + parts = splitOneOf "./" s +instance Read Cidr where + -- | Parse everything or nothing. + readsPrec _ = \s -> + case (octets_from_cidr_string s) of + [oct1, oct2, oct3, oct4] -> + case (maskbits_from_cidr_string s) of + Just mbits -> + [(Cidr (IPv4Address oct1 oct2 oct3 oct4) mbits, "")] + _ -> [] + _ -> [] -- | Given a CIDR, return the minimum valid IPv4 address contained @@ -309,7 +308,7 @@ test_enumerate = addr3 = mk_ip $ toEnum 242 addr4 = mk_ip $ toEnum 243 expected = [addr1, addr2, addr3, addr4] - actual = enumerate $ fromJust $ cidr_from_string "192.168.0.240/30" + actual = enumerate $ read "192.168.0.240/30" test_min_host1 :: Test test_min_host1 = @@ -319,7 +318,7 @@ test_min_host1 = actual where desc = "The minimum host in 10.0.0.0/24 is 10.0.0.0" - actual = show $ min_host (fromJust $ cidr_from_string "10.0.0.0/24") + actual = show $ min_host (read "10.0.0.0/24") expected = "10.0.0.0" @@ -331,7 +330,7 @@ test_max_host1 = actual where desc = "The maximum host in 10.0.0.0/24 is 10.0.0.255" - actual = show $ max_host (fromJust $ cidr_from_string "10.0.0.0/24") + actual = show $ max_host (read "10.0.0.0/24") expected = "10.0.0.255" @@ -344,7 +343,7 @@ test_equality1 = (cidr1 == cidr1) where desc = "10.1.1.0/23 equals itself" - cidr1 = fromJust $ cidr_from_string "10.1.1.0/23" + cidr1 = read "10.1.1.0/23" :: Cidr test_contains1 :: Test @@ -356,8 +355,8 @@ test_contains1 = (cidr1 `contains` cidr2) where desc = "10.1.1.0/23 contains 10.1.1.0/24" - cidr1 = fromJust $ cidr_from_string "10.1.1.0/23" - cidr2 = fromJust $ cidr_from_string "10.1.1.0/24" + cidr1 = read "10.1.1.0/23" + cidr2 = read "10.1.1.0/24" test_contains2 :: Test @@ -369,7 +368,7 @@ test_contains2 = (cidr1 `contains` cidr1) where desc = "10.1.1.0/23 contains itself" - cidr1 = fromJust $ cidr_from_string "10.1.1.0/23" + cidr1 = read "10.1.1.0/23" test_contains_proper1 :: Test @@ -381,8 +380,8 @@ test_contains_proper1 = (cidr1 `contains_proper` cidr2) where desc = "10.1.1.0/23 contains 10.1.1.0/24 properly" - cidr1 = fromJust $ cidr_from_string "10.1.1.0/23" - cidr2 = fromJust $ cidr_from_string "10.1.1.0/24" + cidr1 = read "10.1.1.0/23" + cidr2 = read "10.1.1.0/24" test_contains_proper2 :: Test @@ -394,7 +393,7 @@ test_contains_proper2 = (cidr1 `contains_proper` cidr1) where desc = "10.1.1.0/23 does not contain itself properly" - cidr1 = fromJust $ cidr_from_string "10.1.1.0/23" + cidr1 = read "10.1.1.0/23" test_adjacent1 :: Test @@ -406,8 +405,8 @@ test_adjacent1 = (cidr1 `adjacent` cidr2) where desc = "10.1.0.0/24 is adjacent to 10.1.1.0/24" - cidr1 = fromJust $ cidr_from_string "10.1.0.0/24" - cidr2 = fromJust $ cidr_from_string "10.1.1.0/24" + cidr1 = read "10.1.0.0/24" + cidr2 = read "10.1.1.0/24" test_adjacent2 :: Test @@ -419,8 +418,8 @@ test_adjacent2 = (cidr1 `adjacent` cidr2) where desc = "10.1.0.0/23 is not adjacent to 10.1.0.0/24" - cidr1 = fromJust $ cidr_from_string "10.1.0.0/23" - cidr2 = fromJust $ cidr_from_string "10.1.0.0/24" + cidr1 = read "10.1.0.0/23" + cidr2 = read "10.1.0.0/24" test_adjacent3 :: Test @@ -432,8 +431,8 @@ test_adjacent3 = (cidr1 `adjacent` cidr2) where desc = "10.1.0.0/24 is not adjacent to 10.2.5.0/24" - cidr1 = fromJust $ cidr_from_string "10.1.0.0/24" - cidr2 = fromJust $ cidr_from_string "10.2.5.0/24" + cidr1 = read "10.1.0.0/24" + cidr2 = read "10.2.5.0/24" test_adjacent4 :: Test @@ -445,8 +444,8 @@ test_adjacent4 = (cidr1 `adjacent` cidr2) where desc = "10.1.1.0/24 is not adjacent to 10.1.2.0/24" - cidr1 = fromJust $ cidr_from_string "10.1.1.0/24" - cidr2 = fromJust $ cidr_from_string "10.1.2.0/24" + cidr1 = read "10.1.1.0/24" + cidr2 = read "10.1.2.0/24" test_combine_contained1 :: Test @@ -458,9 +457,9 @@ test_combine_contained1 = (combine_contained test_cidrs) where desc = "10.0.0.0/8, 10.1.0.0/16, and 10.1.1.0/24 combine to 10.0.0.0/8" - cidr1 = fromJust $ cidr_from_string "10.0.0.0/8" - cidr2 = fromJust $ cidr_from_string "10.1.0.0/16" - cidr3 = fromJust $ cidr_from_string "10.1.1.0/24" + cidr1 = read "10.0.0.0/8" + cidr2 = read "10.1.0.0/16" + cidr3 = read "10.1.1.0/24" expected_cidrs = [cidr1] test_cidrs = [cidr1, cidr2, cidr3] @@ -474,8 +473,8 @@ test_combine_contained2 = (combine_contained [cidr1, cidr2]) where desc = "192.168.3.0/23 does not contain 192.168.1.0/24" - cidr1 = fromJust $ cidr_from_string "192.168.3.0/23" - cidr2 = fromJust $ cidr_from_string "192.168.1.0/24" + cidr1 = read "192.168.3.0/23" + cidr2 = read "192.168.1.0/24" test_combine_all1 :: Test @@ -488,12 +487,12 @@ test_combine_all1 = where desc = "10.0.0.0/24 is adjacent to 10.0.1.0/24 " ++ "and 10.0.3.0/23 contains 10.0.2.0/24" - cidr1 = fromJust $ cidr_from_string "10.0.0.0/24" - cidr2 = fromJust $ cidr_from_string "10.0.1.0/24" - cidr3 = fromJust $ cidr_from_string "10.0.2.0/24" - cidr4 = fromJust $ cidr_from_string "10.0.3.0/23" - cidr5 = fromJust $ cidr_from_string "10.0.0.0/23" - expected_cidrs = [fromJust $ cidr_from_string "10.0.0.0/22"] + cidr1 = read "10.0.0.0/24" + cidr2 = read "10.0.1.0/24" + cidr3 = read "10.0.2.0/24" + cidr4 = read "10.0.3.0/23" + cidr5 = read "10.0.0.0/23" + expected_cidrs = [read "10.0.0.0/22"] test_cidrs = [cidr1, cidr2, cidr3, cidr4, cidr5] @@ -506,7 +505,7 @@ test_combine_all2 = (combine_all test_cidrs) where desc = "127.0.0.1/32 combines with itself recursively" - cidr1 = fromJust $ cidr_from_string "127.0.0.1/32" + cidr1 = read "127.0.0.1/32" expected_cidrs = [cidr1] test_cidrs = [cidr1, cidr1, cidr1, cidr1, cidr1] @@ -521,11 +520,11 @@ test_combine_all3 = where desc = "10.0.0.16, 10.0.0.17, 10.0.0.18, and " ++ "10.0.0.19 get combined into 10.0.0.16/30" - cidr1 = fromJust $ cidr_from_string "10.0.0.16/32" - cidr2 = fromJust $ cidr_from_string "10.0.0.17/32" - cidr3 = fromJust $ cidr_from_string "10.0.0.18/32" - cidr4 = fromJust $ cidr_from_string "10.0.0.19/32" - expected_cidrs = [fromJust $ cidr_from_string "10.0.0.16/30"] + cidr1 = read "10.0.0.16/32" + cidr2 = read "10.0.0.17/32" + cidr3 = read "10.0.0.18/32" + cidr4 = read "10.0.0.19/32" + expected_cidrs = [read "10.0.0.16/30"] test_cidrs = [cidr1, cidr2, cidr3, cidr4] diff --git a/src/Main.hs b/src/Main.hs index 5b034ba..f567400 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -11,10 +11,10 @@ import Data.Maybe (catMaybes, isNothing) import Data.String.Utils (splitWs) import System.Exit (ExitCode(..), exitSuccess, exitWith) import System.IO (stderr, hPutStrLn) +import Text.Read (readMaybe) import Cidr ( Cidr(..), - cidr_from_string, combine_all, enumerate, max_octet1, @@ -115,7 +115,7 @@ main = do input <- inputfunc let cidr_strings = splitWs input - let cidrs = map cidr_from_string cidr_strings + let cidrs = map readMaybe cidr_strings when (any isNothing cidrs) $ do putStrLn "Error: not valid CIDR notation." -- 2.43.2