{-# LANGUAGE TemplateHaskell #-} {-| Module: IHP.Postgres.Inet Description: Adds support for storing IP addresses in INET fields. CIDR Notation is not supported at the moment. Copyright: (c) digitally induced GmbH, 2020 -} module IHP.Postgres.Inet where import BasicPrelude import Database.PostgreSQL.Simple.ToField import Database.PostgreSQL.Simple.FromField import qualified Database.PostgreSQL.Simple.TypeInfo.Static as TI import Database.PostgreSQL.Simple.TypeInfo.Macro as TI import Data.Attoparsec.ByteString.Char8 as Attoparsec -- We use the @ip@ package for representing IP addresses import qualified Net.IP as IP import Net.IP (IP) import qualified Data.Text.Encoding as Text instance FromField IP where fromField f v = if typeOid f /= $(inlineTypoid TI.inet) then returnError Incompatible f "" else case v of Nothing -> returnError UnexpectedNull f "" Just bs -> case parseOnly parser bs of Left err -> returnError ConversionFailed f err Right val -> pure val where parser = do ip <- Attoparsec.takeWhile (\char -> char /= ' ') case IP.decode (Text.decodeUtf8 ip) of Just ip -> pure ip Nothing -> fail "Invalid IP" instance ToField IP where toField ip = toField (IP.encode ip)