{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeApplications #-} module Database.PostgreSQL.Opium.ToField ( ToField (..) ) where import Data.Bits (Bits (..)) import Data.ByteString (ByteString) import Data.List (singleton) import Data.Text (Text) import Data.Word (Word32) import Database.PostgreSQL.LibPQ (Format (..), Oid) import Unsafe.Coerce (unsafeCoerce) import qualified Data.ByteString as BS import qualified Data.Text as Text import qualified Data.Text.Encoding as Encoding import qualified Database.PostgreSQL.Opium.Oid as Oid class ToField a where toField :: a -> Maybe (Oid, ByteString, Format) instance ToField ByteString where toField x = Just (Oid.bytea, x, Binary) instance ToField Text where toField x = Just (Oid.text, Encoding.encodeUtf8 x, Binary) instance ToField String where toField = toField . Text.pack instance ToField Char where toField = toField . singleton -- Potentially slow, but good enough for now encodeBigEndian :: (Integral a, Bits a) => Int -> a -> ByteString encodeBigEndian n = BS.pack . go [] n where go acc 0 _ = acc go acc i x = go (fromIntegral (x .&. 0xff) : acc) (i - 1) (x `shiftR` 8) instance ToField Int where toField x = Just (Oid.bigint, encodeBigEndian 8 x, Binary) instance ToField Float where toField x = Just (Oid.real, encodeBigEndian @Word32 4 $ unsafeCoerce x, Binary) instance ToField Double where toField x = Just (Oid.doublePrecision, encodeBigEndian @Word 8 $ unsafeCoerce x, Binary)