module Database.CQL.Protocol.Class (Cql (..)) where
import Control.Applicative
import Control.Arrow
import Data.Decimal
import Data.Int
import Data.IP
import Data.Text (Text)
import Data.Time
import Data.Time.Clock.POSIX
import Data.UUID (UUID)
import Database.CQL.Protocol.Types
import Prelude
class Cql a where
ctype :: Tagged a ColumnType
toCql :: a -> Value
fromCql :: Value -> Either String a
instance Cql Bool where
ctype = Tagged BooleanColumn
toCql = CqlBoolean
fromCql (CqlBoolean b) = Right b
fromCql _ = Left "Expected CqlBoolean."
instance Cql Int32 where
ctype = Tagged IntColumn
toCql = CqlInt
fromCql (CqlInt i) = Right i
fromCql _ = Left "Expected CqlInt."
instance Cql Int64 where
ctype = Tagged BigIntColumn
toCql = CqlBigInt
fromCql (CqlBigInt i) = Right i
fromCql _ = Left "Expected CqlBigInt."
instance Cql Integer where
ctype = Tagged VarIntColumn
toCql = CqlVarInt
fromCql (CqlVarInt i) = Right i
fromCql _ = Left "Expected CqlVarInt."
instance Cql Float where
ctype = Tagged FloatColumn
toCql = CqlFloat
fromCql (CqlFloat f) = Right f
fromCql _ = Left "Expected CqlFloat."
instance Cql Double where
ctype = Tagged DoubleColumn
toCql = CqlDouble
fromCql (CqlDouble d) = Right d
fromCql _ = Left "Expected CqlDouble."
instance Cql Decimal where
ctype = Tagged DecimalColumn
toCql = CqlDecimal
fromCql (CqlDecimal d) = Right d
fromCql _ = Left "Expected CqlDecimal."
instance Cql Text where
ctype = Tagged TextColumn
toCql = CqlText
fromCql (CqlText s) = Right s
fromCql _ = Left "Expected CqlText."
instance Cql Ascii where
ctype = Tagged AsciiColumn
toCql (Ascii a) = CqlAscii a
fromCql (CqlAscii a) = Right $ Ascii a
fromCql _ = Left "Expected CqlAscii."
instance Cql IP where
ctype = Tagged InetColumn
toCql = CqlInet
fromCql (CqlInet i) = Right i
fromCql _ = Left "Expected CqlInet."
instance Cql UUID where
ctype = Tagged UuidColumn
toCql = CqlUuid
fromCql (CqlUuid u) = Right u
fromCql _ = Left "Expected CqlUuid."
instance Cql UTCTime where
ctype = Tagged TimestampColumn
toCql = CqlTimestamp
. truncate
. (* 1000)
. utcTimeToPOSIXSeconds
fromCql (CqlTimestamp t) =
let (s, ms) = t `divMod` 1000
UTCTime a b = posixSecondsToUTCTime (fromIntegral s)
ps = fromIntegral ms * 1000000000
in Right $ UTCTime a (b + picosecondsToDiffTime ps)
fromCql _ = Left "Expected CqlTimestamp."
instance Cql Blob where
ctype = Tagged BlobColumn
toCql (Blob b) = CqlBlob b
fromCql (CqlBlob b) = Right $ Blob b
fromCql _ = Left "Expected CqlBlob."
instance Cql Counter where
ctype = Tagged CounterColumn
toCql (Counter c) = CqlCounter c
fromCql (CqlCounter c) = Right $ Counter c
fromCql _ = Left "Expected CqlCounter."
instance Cql TimeUuid where
ctype = Tagged TimeUuidColumn
toCql (TimeUuid u) = CqlTimeUuid u
fromCql (CqlTimeUuid t) = Right $ TimeUuid t
fromCql _ = Left "Expected TimeUuid."
instance Cql a => Cql [a] where
ctype = Tagged (ListColumn (untag (ctype :: Tagged a ColumnType)))
toCql = CqlList . map toCql
fromCql (CqlList l) = mapM fromCql l
fromCql _ = Left "Expected CqlList."
instance Cql a => Cql (Maybe a) where
ctype = Tagged (MaybeColumn (untag (ctype :: Tagged a ColumnType)))
toCql = CqlMaybe . fmap toCql
fromCql (CqlMaybe (Just m)) = Just <$> fromCql m
fromCql (CqlMaybe Nothing) = Right Nothing
fromCql _ = Left "Expected CqlMaybe."
instance (Cql a, Cql b) => Cql (Map a b) where
ctype = Tagged $ MapColumn
(untag (ctype :: Tagged a ColumnType))
(untag (ctype :: Tagged b ColumnType))
toCql (Map m) = CqlMap $ map (toCql *** toCql) m
fromCql (CqlMap m) = Map <$> mapM (\(k, v) -> (,) <$> fromCql k <*> fromCql v) m
fromCql _ = Left "Expected CqlMap."
instance Cql a => Cql (Set a) where
ctype = Tagged (SetColumn (untag (ctype :: Tagged a ColumnType)))
toCql (Set a) = CqlSet $ map toCql a
fromCql (CqlSet a) = Set <$> mapM fromCql a
fromCql _ = Left "Expected CqlSet."