{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} module Salak.Internal.Val where import Data.ByteString (ByteString) import Data.Heap (Heap) import qualified Data.Heap as H import Data.Int import Data.List (intercalate) import Data.Scientific import Data.Text (Text) import qualified Data.Text as T import Data.Text.Encoding (decodeUtf8) import Data.Time data Val v = Val !Int !v deriving (Eq, Show) data ModType = Add | Mod | Del | Noop deriving (Eq, Show) type Priority = Int priority :: Val v -> Int priority (Val i _) = i data Value = VT !Text | VI !Scientific | VB !Bool | VLT !LocalTime | VD !Day | VH !TimeOfDay | VZT !TimeZone !LocalTime | VU !UTCTime deriving Eq instance Show Value where show v = let (a,b) = typeOfV v in b ++ "::" ++ a typeOfV :: Value -> (String, String) typeOfV (VT b) = ("Str", show b) typeOfV (VI b) = ("Num", show b) typeOfV (VB b) = ("Bool", show b) typeOfV (VLT b) = ("LocalTime", show b) typeOfV (VD b) = ("Day", show b) typeOfV (VH b) = ("TimeOfDay", show b) typeOfV (VZT _ b) = ("ZonedTime", show b) typeOfV (VU b) = ("UTCTime", show b) getType :: Value -> String getType = fst . typeOfV newtype Vals = Vals { unVals :: Heap (Val Value) } deriving Eq instance Show Vals where show (Vals v) = intercalate "," $ go <$> H.toUnsortedList v where go (Val i x) = '#' : show i ++ ('.' : show x) instance Eq v => Ord (Val v) where compare (Val a _) (Val b _) = compare a b nullVals :: Vals -> Bool nullVals (Vals v) = H.null v emptyVals :: Vals emptyVals = Vals H.empty deleteVals :: Int -> Vals -> (Bool, Vals) deleteVals i (Vals v) = let (a,b) = H.partition ((==i) . priority) v in (H.null a, Vals b) getVal :: Vals -> Maybe Value getVal (Vals v) | H.null v = Nothing | otherwise = let Val _ x = H.minimum v in Just x class ToValue a where toVal :: a -> Value instance ToValue Value where toVal = id instance ToValue Text where toVal = VT instance ToValue ByteString where toVal = VT . decodeUtf8 instance ToValue String where toVal = VT . T.pack instance ToValue Scientific where toVal = VI instance ToValue Integer where toVal = VI . fromInteger instance ToValue Int where toVal = VI . fromInteger . toInteger instance ToValue Int64 where toVal = VI . fromInteger . toInteger instance ToValue Double where toVal = VI . realToFrac instance ToValue Bool where toVal = VB instance ToValue UTCTime where toVal = VU delVals :: Int -> Vals -> Vals delVals p (Vals v) = Vals $ H.filter ((/=p) . priority) v modVals :: Val Value -> Vals -> Vals modVals val@(Val p _) (Vals v) = Vals $ H.insert val $ H.filter ((/=p) . priority) v modVals' :: Vals -> Vals -> Vals modVals' (Vals v) vals = if H.null v then vals else modVals (H.minimum v) vals