packages feed

ip-1.7.8: test/IPv4DecodeText1.hs

module IPv4DecodeText1 where

import Control.Monad
import Data.Bits (shiftL, (.|.))
import qualified Data.Text as Text
import Data.Text.Internal (Text (..))
import qualified Data.Text.Read as TextRead
import Data.Word
import Net.Types

stripDecimal :: Text -> Either String Text
stripDecimal t = case Text.uncons t of
  Nothing -> Left "expected a dot but input ended instead"
  Just (c, tnext) ->
    if c == '.'
      then Right tnext
      else Left "expected a dot but found a different character"
{-# INLINE stripDecimal #-}

decodeIPv4TextEither :: Text -> Either String Word32
decodeIPv4TextEither t1' = do
  (a, t2) <- TextRead.decimal t1'
  t2' <- stripDecimal t2
  (b, t3) <- TextRead.decimal t2'
  t3' <- stripDecimal t3
  (c, t4) <- TextRead.decimal t3'
  t4' <- stripDecimal t4
  (d, t5) <- TextRead.decimal t4'
  when (not (Text.null t5)) (Left "expected end of text but it continued instead")
  if a > 255 || b > 255 || c > 255 || d > 255
    then Left ipOctetSizeErrorMsg
    else Right (fromOctets' a b c d)

decodeText :: Text -> Maybe IPv4
decodeText t = case decodeIPv4TextEither t of
  Left _ -> Nothing
  Right w -> Just (IPv4 w)

ipOctetSizeErrorMsg :: String
ipOctetSizeErrorMsg = "All octets in an IPv4 address must be between 0 and 255"

fromOctets' :: Word32 -> Word32 -> Word32 -> Word32 -> Word32
fromOctets' a b c d =
  ( shiftL a 24
      .|. shiftL b 16
      .|. shiftL c 8
      .|. d
  )