{-# LANGUAGE AllowAmbiguousTypes #-}
{-# OPTIONS_HADDOCK hide #-}
module PopKey.Internal3 where
import qualified Data.ByteString as BS
import HaskellWorks.Data.RankSelect.CsPoppy
import qualified HaskellWorks.Data.RankSelect.CsPoppy.Internal.Alpha0 as A0
import qualified HaskellWorks.Data.RankSelect.CsPoppy.Internal.Alpha1 as A1
import Data.Profunctor
import Data.Store (encode , decodeEx)
import GHC.Generics hiding (R)
import GHC.Word
import Unsafe.Coerce
import PopKey.Internal1
import PopKey.Internal2
import PopKey.Encoding
data PopKey k v =
forall s . PopKeyInt !(F s PKPrim) (F' s BS.ByteString -> v) (k -> Int)
| forall s1 s2 . PopKeyAny !(F s1 PKPrim) (F' s1 BS.ByteString -> v) (k -> F' s2 BS.ByteString) !(F s2 PKPrim)
instance Functor (PopKey k) where
{-# INLINE fmap #-}
fmap f (PopKeyInt p d e) = PopKeyInt p (f . d) e
fmap f (PopKeyAny pv d e pk) = PopKeyAny pv (f . d) e pk
instance Profunctor PopKey where
{-# INLINE dimap #-}
dimap f g (PopKeyInt p d e) = PopKeyInt p (g . d) (e . f)
dimap f g (PopKeyAny pv d e pk) = PopKeyAny pv (g . d) (e . f) pk
instance Foldable (PopKey k) where
{-# INLINE foldr #-}
foldr f z p@(PopKeyInt pr vd _) = foldr (\i -> f (vd do rawq i pr)) z [ 0 .. (length p - 1) ]
foldr f z p@(PopKeyAny pr vd _ _) = foldr (\i -> f (vd do rawq i pr)) z [ 0 .. (length p - 1) ]
{-# INLINE length #-}
length (PopKeyInt p _ _) = flength p
length (PopKeyAny _ _ _ p) = flength p
class BiSerialize a where
bencode :: a -> (BS.ByteString , BS.ByteString)
default bencode :: (Generic a , GBiSerialize a (Rep a)) => a -> (BS.ByteString , BS.ByteString)
bencode = gbencode @a @(Rep a) . from
bdecode :: (BS.ByteString , BS.ByteString) -> a
default bdecode :: (Generic a , GBiSerialize a (Rep a)) => (BS.ByteString , BS.ByteString) -> a
bdecode = to . gbdecode @a @(Rep a)
class GBiSerialize s f where
gbencode :: f a -> (BS.ByteString , BS.ByteString)
gbdecode :: (BS.ByteString , BS.ByteString) -> f a
instance GBiSerialize s U1 where
{-# INLINE gbencode #-}
gbencode = const mempty
{-# INLINE gbdecode #-}
gbdecode = const mempty
instance BiSerialize a => GBiSerialize s (K1 i a) where
{-# INLINE gbencode #-}
gbencode (K1 x) = bencode x
{-# INLINE gbdecode #-}
gbdecode = K1 . bdecode
instance (GBiSerialize s a , GBiSerialize s b) => GBiSerialize s (a :*: b) where
{-# INLINE gbencode #-}
gbencode (a :*: b) = do
let (a1 , a2) = gbencode @s a
(b1 , b2) = gbencode @s b
(encode (a1 , b1) , encode (a2 , b2))
{-# INLINE gbdecode #-}
gbdecode (r1 , r2) = do
let (a1 , b1) = decodeEx r1
(a2 , b2) = decodeEx r2
gbdecode @s (a1 , a2) :*: gbdecode @s (b1 , b2)
instance (GBiSerialize s a , GBiSerialize s b) => GBiSerialize s (a :+: b) where
gbencode (L1 x) = do
let (b1 , b2) = gbencode @s x
(encode False <> b1 , b2)
gbencode (R1 x) = do
let (b1 , b2) = gbencode @s x
(encode True <> b1 , b2)
gbdecode ((BS.splitAt 1 -> (b , b1)) , b2) =
if decodeEx b
then R1 (gbdecode @s (b1 , b2))
else L1 (gbdecode @s (b1 , b2))
instance GBiSerialize s f => GBiSerialize s (M1 i t f) where
{-# INLINE gbencode #-}
gbencode (M1 x) = gbencode @s x
{-# INLINE gbdecode #-}
gbdecode = M1 . gbdecode @s
instance BiSerialize CsPoppy where
bencode (CsPoppy bv (A0.CsPoppyIndex a01 a02) (A1.CsPoppyIndex a11 a12)) =
(,) do encode (a01 , a02 , a11 , a12)
do encode bv
bdecode (bs , bv) = do
let (a01 , a02 , a11 , a12) = decodeEx bs
CsPoppy (decodeEx bv) (A0.CsPoppyIndex a01 a02) (A1.CsPoppyIndex a11 a12)
instance BiSerialize BS.ByteString where
{-# INLINE bencode #-}
bencode x = (mempty , x)
{-# INLINE bdecode #-}
bdecode (_ , x) = x
instance BiSerialize Word32 where
{-# INLINE bencode #-}
bencode x = (encode x , mempty)
{-# INLINE bdecode #-}
bdecode (x , _) = decodeEx x
instance BiSerialize PKPrim
instance BiSerialize a => BiSerialize (Maybe a)
instance (BiSerialize a , BiSerialize b) => BiSerialize (a , b)
data Custom = Custom {-# UNPACK #-} !Word32 CsPoppy
instance BiSerialize Custom where
bencode (Custom l ppy) = do
let x :: Maybe (Word32 , CsPoppy) =
if l == 0
then Nothing
else Just (l , ppy)
bencode x
bdecode r = case bdecode r of
Nothing -> Custom 0 undefined
Just (l , ppy) -> Custom l ppy
data SF a =
SSingle a
| SProd !(SF a) !(SF a)
| SSum !Custom !(SF a) !(SF a)
deriving (Generic,BiSerialize)
fromF :: F s a -> SF a
fromF (Single x) = SSingle x
fromF (Prod x y) = SProd (fromF x) (fromF y)
fromF (Sum l ppy x y) = SSum (Custom l ppy) (fromF x) (fromF y)
toF :: SF a -> F s a
toF (SSingle x) = unsafeCoerce do Single x
toF (SProd x y) = unsafeCoerce do Prod (toF x) (toF y)
toF (SSum (Custom l ppy) x y) = unsafeCoerce do Sum l ppy (toF x) (toF y)
data SPopKey k v =
SPopKeyInt !(SF PKPrim)
| SPopKeyAny !(SF PKPrim) !(SF PKPrim)
deriving (Generic,BiSerialize)
toSPopKey :: PopKey k v -> SPopKey k v
toSPopKey (PopKeyInt p _ _) = SPopKeyInt (fromF p)
toSPopKey (PopKeyAny p1 _ _ p2) = SPopKeyAny (fromF p1) (fromF p2)
fromSPopKey :: forall k v . (PopKeyEncoding k , PopKeyEncoding v) => SPopKey k v -> PopKey k v
fromSPopKey (SPopKeyInt p) = PopKeyInt (toF p) (pkDecode @v) (unsafeCoerce id)
fromSPopKey (SPopKeyAny pv pk) = PopKeyAny (toF pv) (pkDecode @v) (pkEncode @k) (toF pk)
fromSPopKey' :: PopKeyEncoding v => SPopKey Int v -> PopKey Int v
fromSPopKey' (SPopKeyInt p) = PopKeyInt (toF p) pkDecode (unsafeCoerce id)
fromSPopKey' _ = error "Incorrect PopKey type: expected Int."
data PopKeyStore k v =
PopKeyStore (forall f . Foldable f => f (k , v) -> IO ())
(IO (PopKey k v))
data PopKeyStore' v =
PopKeyStore' (forall f . Foldable f => f v -> IO ())
(IO (PopKey Int v))
class StorePopKey k v f | f -> k , f -> v where
type Input f
storePopKey :: Foldable t => f -> t (Input f) -> IO ()
loadPopKey :: f -> IO (PopKey k v)
instance StorePopKey k v (PopKeyStore k v) where
type Input (PopKeyStore k v) = (k , v)
storePopKey (PopKeyStore a _) = a
loadPopKey (PopKeyStore _ b) = b
instance StorePopKey Int v (PopKeyStore' v) where
type Input (PopKeyStore' v) = v
storePopKey (PopKeyStore' a _) = a
loadPopKey (PopKeyStore' _ b) = b