packages feed

sqel-0.0.1.0: lib/Sqel/Codec/PrimEncoder.hs

module Sqel.Codec.PrimEncoder where

import qualified Chronos as Chronos
import Data.Scientific (Scientific)
import Data.Time (Day (ModifiedJulianDay), DiffTime, LocalTime (LocalTime), TimeOfDay (TimeOfDay), TimeZone, UTCTime)
import Data.UUID (UUID)
import Hasql.Encoders (
  Value,
  array,
  bool,
  bytea,
  char,
  date,
  dimension,
  element,
  float4,
  float8,
  int2,
  int4,
  int8,
  interval,
  nonNullable,
  numeric,
  text,
  time,
  timestamp,
  timestamptz,
  timetz,
  uuid,
  )
import Path (Path, toFilePath)
import Prelude hiding (bool)

class PrimEncoder d where
  primEncoder :: Value d

instance PrimEncoder () where
  primEncoder =
    True >$ bool

instance PrimEncoder Bool where
  primEncoder =
    bool

instance PrimEncoder Int16 where
  primEncoder =
    int2

instance PrimEncoder Int32 where
  primEncoder =
    int4

instance PrimEncoder Int64 where
  primEncoder =
    int8

instance PrimEncoder Int where
  primEncoder =
    contramap fromIntegral int8

instance PrimEncoder Float where
  primEncoder =
    float4

instance PrimEncoder Double where
  primEncoder =
    float8

instance PrimEncoder Scientific where
  primEncoder =
    numeric

instance PrimEncoder Char where
  primEncoder =
    char

instance PrimEncoder Text where
  primEncoder =
    text

instance PrimEncoder ByteString where
  primEncoder =
    bytea

instance PrimEncoder Day where
  primEncoder =
    date

instance PrimEncoder LocalTime where
  primEncoder =
    timestamp

instance PrimEncoder UTCTime where
  primEncoder =
    timestamptz

instance PrimEncoder TimeOfDay where
  primEncoder =
    time

instance PrimEncoder (TimeOfDay, TimeZone) where
  primEncoder =
    timetz

instance PrimEncoder DiffTime where
  primEncoder =
    interval

instance PrimEncoder UUID where
  primEncoder =
    uuid

instance PrimEncoder (Path b t) where
  primEncoder =
    (toText . toFilePath) >$< text

chronosToDay :: Chronos.Date -> Day
chronosToDay =
  ModifiedJulianDay . fromIntegral . Chronos.getDay . Chronos.dateToDay

instance PrimEncoder Chronos.Date where
  primEncoder =
    chronosToDay >$< date

instance PrimEncoder Chronos.Time where
  primEncoder =
    Chronos.getTime >$< int8

chronosToTimeOfDay :: Chronos.TimeOfDay -> TimeOfDay
chronosToTimeOfDay (Chronos.TimeOfDay h m ns) =
  TimeOfDay h m (fromMaybe 0 (realToFrac ns / 1000000000))

datetimeToLocalTime :: Chronos.Datetime -> LocalTime
datetimeToLocalTime (Chronos.Datetime d t) =
  LocalTime (chronosToDay d) (chronosToTimeOfDay t)

instance PrimEncoder Chronos.Datetime where
  primEncoder =
     datetimeToLocalTime >$< primEncoder

arrayEncoder ::
  Foldable f =>
  Value a ->
  Value (f a)
arrayEncoder =
  array .
  dimension foldl' .
  element .
  nonNullable