module Data.SafeCopy.Store.Instances where
import Data.SafeCopy.Store.SafeCopy
import Data.SafeCopy.Store.Encode
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative
#endif
import Control.Monad
import qualified Data.Array as Array
import qualified Data.Array.Unboxed as UArray
import qualified Data.Array.IArray as IArray
import qualified Data.ByteString.Lazy.Char8 as L
import qualified Data.ByteString.Char8 as B
import qualified Data.Foldable as Foldable
import Data.Fixed (HasResolution, Fixed)
import Data.Int
import qualified Data.IntMap as IntMap
import qualified Data.IntSet as IntSet
import Data.Ix
import qualified Data.Map as Map
import Data.Ratio (Ratio, (%), numerator, denominator)
import qualified Data.Sequence as Sequence
import Data.Store
import qualified Data.Set as Set
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TL
import Data.Time.Calendar (Day(..))
import Data.Time.Clock (DiffTime, NominalDiffTime, UniversalTime(..), UTCTime(..))
import Data.Time.Clock.TAI (AbsoluteTime, taiEpoch, addAbsoluteTime, diffAbsoluteTime)
import Data.Time.LocalTime (LocalTime(..), TimeOfDay(..), TimeZone(..), ZonedTime(..))
import qualified Data.Tree as Tree
#if MIN_VERSION_base(4,7,0)
import Data.Typeable hiding (Proxy)
#else
import Data.Typeable
#endif
import Data.Word
import System.Time (ClockTime(..), TimeDiff(..), CalendarTime(..), Month(..))
import qualified System.Time as OT
import qualified Data.Vector as V
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Primitive as VP
import qualified Data.Vector.Storable as VS
import qualified Data.Vector.Unboxed as VU
instance SafeCopy a => SafeCopy (Prim a) where
kind = primitive
getCopy = contain $
do e <- unsafeUnPack getCopy
return $ Prim e
putCopy (Prim e)
= contain $ unsafeUnPack (putCopy e) >> pure (Prim e)
instance SafeCopy a => SafeCopy [a] where
getCopy = contain $ do
n <- peek
g <- getSafeGet
go g [] n
where
go :: Peek a -> [a] -> Int -> Peek [a]
go _ as 0 = return (reverse as)
go g as i = do x <- g
x `seq` go g (x:as) (i 1)
putCopy lst = contain $ do void $ pokeE (length lst)
getSafePut >>= forM lst
errorTypeName = typeName1
instance SafeCopy a => SafeCopy (Maybe a) where
getCopy = contain $ do n <- peek
if n then fmap Just safeGet
else return Nothing
putCopy (Just a) = contain $ pokeE True >> safePut a >> pure (Just a)
putCopy Nothing = contain $ pokeE False >> pure Nothing
errorTypeName = typeName1
instance (SafeCopy a, Ord a) => SafeCopy (Set.Set a) where
getCopy = contain $ fmap Set.fromDistinctAscList safeGet
putCopy a = contain $ safePut (Set.toAscList a) >> pure a
errorTypeName = typeName1
instance (SafeCopy a, SafeCopy b, Ord a) => SafeCopy (Map.Map a b) where
getCopy = contain $ fmap Map.fromDistinctAscList safeGet
putCopy a = contain $ safePut (Map.toAscList a) >> pure a
errorTypeName = typeName2
instance (SafeCopy a) => SafeCopy (IntMap.IntMap a) where
getCopy = contain $ fmap IntMap.fromDistinctAscList safeGet
putCopy a = contain $ safePut (IntMap.toAscList a) >> pure a
errorTypeName = typeName1
instance SafeCopy IntSet.IntSet where
getCopy = contain $ fmap IntSet.fromDistinctAscList safeGet
putCopy a = contain $ safePut (IntSet.toAscList a) >> pure a
errorTypeName = typeName
instance (SafeCopy a) => SafeCopy (Sequence.Seq a) where
getCopy = contain $ fmap Sequence.fromList safeGet
putCopy a = contain $ safePut (Foldable.toList a) >> pure a
errorTypeName = typeName1
instance (SafeCopy a) => SafeCopy (Tree.Tree a) where
getCopy = contain $ liftM2 Tree.Node safeGet safeGet
putCopy a@(Tree.Node root sub) = contain $ safePut root >> safePut sub >> pure a
errorTypeName = typeName1
iarray_getCopy :: (Ix i, SafeCopy e, SafeCopy i, IArray.IArray a e) => Contained (Peek (a i e))
iarray_getCopy = contain $ do getIx <- getSafeGet
liftM3 mkArray getIx getIx safeGet
where
mkArray l h = IArray.listArray (l, h)
iarray_putCopy :: (Ix i, SafeCopy e, SafeCopy i, IArray.IArray a e) => a i e -> Contained (Encode (a i e))
iarray_putCopy arr = contain $ do putIx <- getSafePut
let (l,h) = IArray.bounds arr
_ <- putIx l >> putIx h
_ <- safePut (IArray.elems arr)
pure arr
instance (Ix i, SafeCopy e, SafeCopy i) => SafeCopy (Array.Array i e) where
getCopy = iarray_getCopy
putCopy = iarray_putCopy
errorTypeName = typeName2
instance (IArray.IArray UArray.UArray e, Ix i, SafeCopy e, SafeCopy i) => SafeCopy (UArray.UArray i e) where
getCopy = iarray_getCopy
putCopy = iarray_putCopy
errorTypeName = typeName2
instance (SafeCopy a, SafeCopy b) => SafeCopy (a,b) where
getCopy = contain $ liftM2 (,) safeGet safeGet
putCopy (a,b) = contain $ safePut a >> safePut b >> pure (a,b)
errorTypeName = typeName2
instance (SafeCopy a, SafeCopy b, SafeCopy c) => SafeCopy (a,b,c) where
getCopy = contain $ liftM3 (,,) safeGet safeGet safeGet
putCopy (a,b,c) = contain $ safePut a >> safePut b >> safePut c >> pure (a,b,c)
instance (SafeCopy a, SafeCopy b, SafeCopy c, SafeCopy d) => SafeCopy (a,b,c,d) where
getCopy = contain $ liftM4 (,,,) safeGet safeGet safeGet safeGet
putCopy (a,b,c,d) = contain $ safePut a >> safePut b >> safePut c >> safePut d >> pure (a,b,c,d)
instance (SafeCopy a, SafeCopy b, SafeCopy c, SafeCopy d, SafeCopy e) =>
SafeCopy (a,b,c,d,e) where
getCopy = contain $ liftM5 (,,,,) safeGet safeGet safeGet safeGet safeGet
putCopy (a,b,c,d,e) = contain $ safePut a >> safePut b >> safePut c >> safePut d >> safePut e >> pure (a,b,c,d,e)
instance (SafeCopy a, SafeCopy b, SafeCopy c, SafeCopy d, SafeCopy e, SafeCopy f) =>
SafeCopy (a,b,c,d,e,f) where
getCopy = contain $ (,,,,,) <$> safeGet <*> safeGet <*> safeGet <*> safeGet <*> safeGet <*> safeGet
putCopy (a,b,c,d,e,f) = contain $ safePut a >> safePut b >> safePut c >> safePut d >>
safePut e >> safePut f >> pure (a,b,c,d,e,f)
instance (SafeCopy a, SafeCopy b, SafeCopy c, SafeCopy d, SafeCopy e, SafeCopy f, SafeCopy g) =>
SafeCopy (a,b,c,d,e,f,g) where
getCopy = contain $ (,,,,,,) <$> safeGet <*> safeGet <*> safeGet <*> safeGet <*>
safeGet <*> safeGet <*> safeGet
putCopy (a,b,c,d,e,f,g) = contain $ safePut a >> safePut b >> safePut c >> safePut d >>
safePut e >> safePut f >> safePut g >> pure (a,b,c,d,e,f,g)
instance SafeCopy Int where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy Integer where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
newtype CerealFloat040 = CerealFloat040 { unCerealFloat040 :: Float} deriving (Show, Typeable)
instance SafeCopy CerealFloat040 where
getCopy = contain (CerealFloat040 <$> liftM2 encodeFloat peek peek)
putCopy a@(CerealFloat040 float) = contain $ pokeE (decodeFloat float) >> pure a
errorTypeName = typeName
instance Migrate Float where
type MigrateFrom Float = CerealFloat040
migrate (CerealFloat040 d) = d
instance SafeCopy Float where
version = Version 1
kind = extension
getCopy = contain peek
putCopy = contain . pokeE
errorTypeName = typeName
newtype CerealDouble040 = CerealDouble040 { unCerealDouble040 :: Double} deriving (Show, Typeable)
instance SafeCopy CerealDouble040 where
getCopy = contain (CerealDouble040 <$> liftM2 encodeFloat peek peek)
putCopy a@(CerealDouble040 double) = contain $ pokeE (decodeFloat double) >> pure a
errorTypeName = typeName
instance Migrate Double where
type MigrateFrom Double = CerealDouble040
migrate (CerealDouble040 d) = d
instance SafeCopy Double where
version = Version 1
kind = extension
getCopy = contain peek
putCopy = contain . pokeE
errorTypeName = typeName
instance Store Ordering
instance SafeCopy L.ByteString where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy B.ByteString where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy Char where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy Word where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy Word8 where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy Word16 where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy Word32 where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy Word64 where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy Ordering where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy Int8 where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy Int16 where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy Int32 where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy Int64 where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance (Integral a, SafeCopy a) => SafeCopy (Ratio a) where
getCopy = contain $ do n <- safeGet
d <- safeGet
return (n % d)
putCopy r = contain $ do void $ safePut (numerator r)
void $ safePut (denominator r)
pure r
errorTypeName = typeName1
instance (HasResolution a, Fractional (Fixed a)) => SafeCopy (Fixed a) where
getCopy = contain $ fromRational <$> safeGet
putCopy a = contain $ safePut (toRational a) >> pure a
errorTypeName = typeName1
instance SafeCopy () where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance SafeCopy Bool where
getCopy = contain peek; putCopy = contain . pokeE; errorTypeName = typeName
instance (SafeCopy a, SafeCopy b) => SafeCopy (Either a b) where
getCopy = contain $ do n <- peek
if n then fmap Right safeGet
else fmap Left safeGet
putCopy e@(Right a) = contain $ pokeE True >> safePut a >> pure e
putCopy e@(Left a) = contain $ pokeE False >> safePut a >> pure e
errorTypeName = typeName2
instance SafeCopy T.Text where
kind = base
getCopy = contain $ T.decodeUtf8 <$> safeGet
putCopy e = contain $ safePut (T.encodeUtf8 e) >> pure e
errorTypeName = typeName
instance SafeCopy TL.Text where
kind = base
getCopy = contain $ TL.decodeUtf8 <$> safeGet
putCopy e = contain $ safePut (TL.encodeUtf8 e) >> pure e
errorTypeName = typeName
instance SafeCopy Day where
kind = base
getCopy = contain $ ModifiedJulianDay <$> safeGet
putCopy e = contain $ safePut (toModifiedJulianDay e) >> pure e
errorTypeName = typeName
instance SafeCopy DiffTime where
kind = base
getCopy = contain $ fromRational <$> safeGet
putCopy e = contain $ safePut (toRational e) >> pure e
errorTypeName = typeName
instance SafeCopy UniversalTime where
kind = base
getCopy = contain $ ModJulianDate <$> safeGet
putCopy e = contain $ safePut (getModJulianDate e) >> pure e
errorTypeName = typeName
instance SafeCopy UTCTime where
kind = base
getCopy = contain $ do day <- safeGet
diffTime <- safeGet
return (UTCTime day diffTime)
putCopy u = contain $ do void $ safePut (utctDay u)
void $ safePut (utctDayTime u)
pure u
errorTypeName = typeName
instance SafeCopy NominalDiffTime where
kind = base
getCopy = contain $ fromRational <$> safeGet
putCopy e = contain $ safePut (toRational e) >> pure e
errorTypeName = typeName
instance SafeCopy TimeOfDay where
kind = base
getCopy = contain $ do hour <- safeGet
mins <- safeGet
sec <- safeGet
return (TimeOfDay hour mins sec)
putCopy t = contain $ do void $ safePut (todHour t)
void $ safePut (todMin t)
void $ safePut (todSec t)
pure t
errorTypeName = typeName
instance SafeCopy TimeZone where
kind = base
getCopy = contain $ do mins <- safeGet
summerOnly <- safeGet
zoneName <- safeGet
return (TimeZone mins summerOnly zoneName)
putCopy t = contain $ do void $ safePut (timeZoneMinutes t)
void $ safePut (timeZoneSummerOnly t)
void $ safePut (timeZoneName t)
pure t
errorTypeName = typeName
instance SafeCopy LocalTime where
kind = base
getCopy = contain $ do day <- safeGet
tod <- safeGet
return (LocalTime day tod)
putCopy t = contain $ do void $ safePut (localDay t)
void $ safePut (localTimeOfDay t)
pure t
errorTypeName = typeName
instance SafeCopy ZonedTime where
kind = base
getCopy = contain $ do localTime <- safeGet
timeZone <- safeGet
return (ZonedTime localTime timeZone)
putCopy t = contain $ do void $ safePut (zonedTimeToLocalTime t)
void $ safePut (zonedTimeZone t)
pure t
errorTypeName = typeName
instance SafeCopy AbsoluteTime where
getCopy = contain $ fmap toAbsoluteTime safeGet
where
toAbsoluteTime :: DiffTime -> AbsoluteTime
toAbsoluteTime dt = addAbsoluteTime dt taiEpoch
putCopy e = contain $ safePut (fromAbsoluteTime e) >> pure e
where
fromAbsoluteTime :: AbsoluteTime -> DiffTime
fromAbsoluteTime at = diffAbsoluteTime at taiEpoch
errorTypeName = typeName
instance SafeCopy ClockTime where
kind = base
getCopy = contain $ do secs <- safeGet
pico <- safeGet
return (TOD secs pico)
putCopy e@(TOD secs pico) =
contain $ do void $ safePut secs
void $ safePut pico
pure e
instance SafeCopy TimeDiff where
kind = base
getCopy = contain $ do year <- peek
month <- peek
day <- peek
hour <- peek
mins <- peek
sec <- peek
pico <- peek
return (TimeDiff year month day hour mins sec pico)
putCopy t = contain $ do void $ pokeE (tdYear t)
void $ pokeE (tdMonth t)
void $ pokeE (tdDay t)
void $ pokeE (tdHour t)
void $ pokeE (tdMin t)
void $ pokeE (tdSec t)
void $ pokeE (tdPicosec t)
pure t
instance SafeCopy OT.Day where
kind = base ; getCopy = contain $ toEnum <$> peek ; putCopy a = contain $ pokeE (fromEnum a) >> pure a
instance SafeCopy Month where
kind = base ; getCopy = contain $ toEnum <$> peek ; putCopy a = contain $ pokeE (fromEnum a) >> pure a
instance SafeCopy CalendarTime where
kind = base
getCopy = contain $ do year <- peek
month <- safeGet
day <- peek
hour <- peek
mins <- peek
sec <- peek
pico <- peek
wday <- safeGet
yday <- peek
tzname <- safeGet
tz <- peek
dst <- peek
return (CalendarTime year month day hour mins sec pico wday yday tzname tz dst)
putCopy t = contain $ do void $ pokeE (ctYear t)
void $ safePut (ctMonth t)
void $ pokeE (ctDay t)
void $ pokeE (ctHour t)
void $ pokeE (ctMin t)
void $ pokeE (ctSec t)
void $ pokeE (ctPicosec t)
void $ safePut (ctWDay t)
void $ pokeE (ctYDay t)
void $ safePut (ctTZName t)
void $ pokeE (ctTZ t)
void $ pokeE (ctIsDST t)
pure t
typeName :: Typeable a => Proxy a -> String
typeName proxy = show (typeOf (undefined `asProxyType` proxy))
typeName1 :: (Typeable c) => Proxy (c a) -> String
typeName1 proxy = show (typeOf1 (undefined `asProxyType` proxy))
typeName2 :: (Typeable c) => Proxy (c a b) -> String
typeName2 proxy = show (typeOf2 (undefined `asProxyType` proxy))
getGenericVector :: (SafeCopy a, VG.Vector v a) => Contained (Peek (v a))
getGenericVector = contain $ do n <- peek
getSafeGet >>= VG.replicateM n
putGenericVector :: (SafeCopy a, VG.Vector v a) => v a -> Contained (Encode (v a))
putGenericVector v = contain $ do void $ pokeE (VG.length v)
getSafePut >>= VG.forM v
instance SafeCopy a => SafeCopy (V.Vector a) where
getCopy = getGenericVector
putCopy = putGenericVector
instance (SafeCopy a, VP.Prim a) => SafeCopy (VP.Vector a) where
getCopy = getGenericVector
putCopy = putGenericVector
instance (SafeCopy a, VS.Storable a) => SafeCopy (VS.Vector a) where
getCopy = getGenericVector
putCopy = putGenericVector
instance (SafeCopy a, VU.Unbox a) => SafeCopy (VU.Vector a) where
getCopy = getGenericVector
putCopy = putGenericVector