IPv4 and IPv6 ranges.
This commit is contained in:
parent
fe3996829b
commit
0684286805
@ -1,7 +1,7 @@
|
|||||||
-- | `IPAddress` is a parser for internet protocol addresses (both IPv4 and IPv6).
|
-- | `IPAddress` is a parser for internet protocol addresses (both IPv4 and IPv6).
|
||||||
module GenericParser.IPAddress where
|
module GenericParser.IPAddress where
|
||||||
|
|
||||||
import Prelude (Ordering(..), compare, (==), (<>), (<), (+), (-), bind, pure, ($), (<<<), (>), show, map, unit)
|
import Prelude (Ordering(..), compare, (==), (<>), (<), (+), (-), between, bind, pure, ($), (<<<), (>), show, map, unit)
|
||||||
|
|
||||||
import Control.Alt ((<|>))
|
import Control.Alt ((<|>))
|
||||||
import Data.Array as A
|
import Data.Array as A
|
||||||
@ -12,7 +12,7 @@ import GenericParser.Parser (Parser(..)
|
|||||||
, failureError
|
, failureError
|
||||||
, current_position
|
, current_position
|
||||||
, string
|
, string
|
||||||
, many1, lookahead
|
, read_input, many1, lookahead
|
||||||
, char)
|
, char)
|
||||||
import GenericParser.BaseFunctions (repeat)
|
import GenericParser.BaseFunctions (repeat)
|
||||||
import GenericParser.SomeParsers (nat)
|
import GenericParser.SomeParsers (nat)
|
||||||
@ -23,6 +23,7 @@ data IPv6Error
|
|||||||
| IP6NotEnoughChunks
|
| IP6NotEnoughChunks
|
||||||
| IP6TooManyChunks
|
| IP6TooManyChunks
|
||||||
| IP6IrrelevantShortRepresentation
|
| IP6IrrelevantShortRepresentation
|
||||||
|
| IP6InvalidRange
|
||||||
|
|
||||||
-- | `ipv6_chunk` parses just a group of hexadecimal characters.
|
-- | `ipv6_chunk` parses just a group of hexadecimal characters.
|
||||||
-- | Return an error (IP6TooManyHexaDecimalCharacters) in case the group has more than 4 characters.
|
-- | Return an error (IP6TooManyHexaDecimalCharacters) in case the group has more than 4 characters.
|
||||||
@ -79,9 +80,22 @@ ipv6_shortened =
|
|||||||
ipv6 :: Parser IPv6Error String
|
ipv6 :: Parser IPv6Error String
|
||||||
ipv6 = ipv6_shortened <|> ipv6_full
|
ipv6 = ipv6_shortened <|> ipv6_full
|
||||||
|
|
||||||
|
-- | `ipv6_range` parses an ipv6 range, such as "2001::1/56".
|
||||||
|
-- | If the parsing succeed, the whole string is returned.
|
||||||
|
ipv6_range :: Parser IPv6Error String
|
||||||
|
ipv6_range =
|
||||||
|
read_input do _ <- ipv6
|
||||||
|
_ <- char '/'
|
||||||
|
pos <- current_position
|
||||||
|
n <- nat
|
||||||
|
if between 0 128 n
|
||||||
|
then pure ""
|
||||||
|
else Parser \_ -> failureError pos (Just IP6InvalidRange)
|
||||||
|
|
||||||
data IPv4Error
|
data IPv4Error
|
||||||
= IP4NumberTooBig Int
|
= IP4NumberTooBig Int
|
||||||
| IP4IrrelevantShortRepresentation
|
| IP4IrrelevantShortRepresentation
|
||||||
|
| IP4InvalidRange
|
||||||
|
|
||||||
-- | `ipv4_byte` a parser for 0 to 255 natural integers, which is part of the representation of an IPv4 address.
|
-- | `ipv4_byte` a parser for 0 to 255 natural integers, which is part of the representation of an IPv4 address.
|
||||||
ipv4_byte :: Parser IPv4Error Int
|
ipv4_byte :: Parser IPv4Error Int
|
||||||
@ -127,3 +141,15 @@ ipv4_shortened =
|
|||||||
|
|
||||||
ipv4 :: Parser IPv4Error String
|
ipv4 :: Parser IPv4Error String
|
||||||
ipv4 = ipv4_shortened <|> ipv4_generic4bytes
|
ipv4 = ipv4_shortened <|> ipv4_generic4bytes
|
||||||
|
|
||||||
|
-- | `ipv4_range` parses an ipv4 range, such as "192.0.2.0/24".
|
||||||
|
-- | If the parsing succeed, the whole string is returned.
|
||||||
|
ipv4_range :: Parser IPv4Error String
|
||||||
|
ipv4_range =
|
||||||
|
read_input do _ <- ipv4
|
||||||
|
_ <- char '/'
|
||||||
|
pos <- current_position
|
||||||
|
n <- nat
|
||||||
|
if between 0 32 n
|
||||||
|
then pure ""
|
||||||
|
else Parser \_ -> failureError pos (Just IP4InvalidRange)
|
||||||
|
@ -73,10 +73,12 @@ showerror_ipv6 (IP.IP6TooManyHexaDecimalCharacters) = "TooManyHexaDecimalCharact
|
|||||||
showerror_ipv6 (IP.IP6NotEnoughChunks) = "NotEnoughChunks"
|
showerror_ipv6 (IP.IP6NotEnoughChunks) = "NotEnoughChunks"
|
||||||
showerror_ipv6 (IP.IP6TooManyChunks) = "TooManyChunks"
|
showerror_ipv6 (IP.IP6TooManyChunks) = "TooManyChunks"
|
||||||
showerror_ipv6 IP.IP6IrrelevantShortRepresentation = "useless double dots"
|
showerror_ipv6 IP.IP6IrrelevantShortRepresentation = "useless double dots"
|
||||||
|
showerror_ipv6 IP.IP6InvalidRange = "invalid IPv6 range"
|
||||||
|
|
||||||
showerror_ipv4 :: IP.IPv4Error -> String
|
showerror_ipv4 :: IP.IPv4Error -> String
|
||||||
showerror_ipv4 (IP4NumberTooBig x) = "value '" <> show x <> "' is > 255"
|
showerror_ipv4 (IP4NumberTooBig x) = "value '" <> show x <> "' is > 255"
|
||||||
showerror_ipv4 IP4IrrelevantShortRepresentation = "useless double dots"
|
showerror_ipv4 IP4IrrelevantShortRepresentation = "useless double dots"
|
||||||
|
showerror_ipv4 IP4InvalidRange = "invalid IPv4 range"
|
||||||
|
|
||||||
showerror_email :: EA.EmailError -> String
|
showerror_email :: EA.EmailError -> String
|
||||||
showerror_email EA.InvalidCharacter = "InvalidCharacter"
|
showerror_email EA.InvalidCharacter = "InvalidCharacter"
|
||||||
@ -125,3 +127,11 @@ main = do
|
|||||||
|
|
||||||
log "Does parsers behave correctly (give the exact same input)?"
|
log "Does parsers behave correctly (give the exact same input)?"
|
||||||
foreachE T.valid_email_addresses_short (\s -> compare_parsers "E.address" (P.read_input E.address) E.address s)
|
foreachE T.valid_email_addresses_short (\s -> compare_parsers "E.address" (P.read_input E.address) E.address s)
|
||||||
|
|
||||||
|
log ""
|
||||||
|
let ip4ranges = [ "10.0.0.1/24", "192.168.0.1/32", "1.2.3.4/0", "192.168.0.1/33" ]
|
||||||
|
test_series "IP.ipv4_range" IP.ipv4_range id showerror_ipv4 ip4ranges
|
||||||
|
|
||||||
|
log ""
|
||||||
|
let ip6ranges = [ "2001::1/56", "2001:1:1::1/0", "::1/128", "::1/129" ]
|
||||||
|
test_series "IP.ipv6_range" IP.ipv6_range id showerror_ipv6 ip6ranges
|
||||||
|
Loading…
Reference in New Issue
Block a user