Vlam
Vlam

Reputation: 1798

How to parse IP address into IP number in Haskell?

What would be the easiest way to take a string containing either IPv4 or IPv6 address and get the IP number?

Upvotes: 2

Views: 1188

Answers (3)

palik
palik

Reputation: 2853

2018 was released ip package, which is very convenient for the purpose.

Decode

λ> import Net.IP
λ> :set -XOverloadedStrings
λ> decode "127.0.0.1"
Just (ipv4 127 0 0 1)
λ> decode "2a02:2450:dd1f:0:7646:a0ff:fe91:67b1"
Just (ipv6 0x2a02 0x2450 0xdd1f 0x0000 0x7646 0xa0ff 0xfe91 0x67b1)

Encode

λ> encode (ipv4 127 0 0 1)
"127.0.0.1"
λ> encode (ipv6 0x2a02 0x2450 0xdd1f 0x0000 0x7646 0xa0ff 0xfe91 0x67b1)
"2a02:2450:dd1f::7646:a0ff:fe91:67b1

The package provides Attoparsec integration.

Upvotes: 1

Michael Szvetits
Michael Szvetits

Reputation: 384

Here is a copy-ready solution:

module Program where

import Data.IP

ipToOcts :: IP -> [Int]
ipToOcts (IPv4 ip) = fromIPv4 ip
ipToOcts (IPv6 ip) = fromIPv6b ip

ipToInteger :: IP -> Integer
ipToInteger =
    sum . map (\(n,o) -> toInteger o * 256 ^ n) . zip [0..] . reverse . ipToOcts

ipStringToInteger :: String -> Integer
ipStringToInteger = ipToInteger . read

Example calls:

ipStringToInteger "134.244.11.55"
ipStringToInteger "2001:db8:00:00:00:00:00:01"

You need the iproute package for that:

cabal install iproute

Upvotes: 2

chepner
chepner

Reputation: 530833

Data.IP has IPv4 and IPv6 types which support parsing from strings, as well as functions for converting them into lists of Int values.

> fromIPv4 . read "192.0.0.1"
[192,0,0,1]
> fromIPv6b . read "2001:0db8::1"
[32,1,13,184,0,0,0,0,0,0,0,0,0,0,0,1]

Once you have the list, you can fold it to a single integer if you like:

> import Data.List
> foldl' (\acc octet -> 256*acc + fromIntegral octet) 0 [192,0,0,1]
3221225473

(Since both fromIPv4 and fromIPv6 return [Int] values, fromIntegeral ensures that the fold can return an Integer.)

However, consider whether you actually need a single integer. Any API you have is really going to be concerned with the individual bytes in the correct order. Other than serializing an address to a binary file, you probably don't even need that.

Upvotes: 2

Related Questions