module Data.BTree.Impure.Structures (
Tree(..)
, Node(..)
, LeafItems
, LeafValue(..)
, putLeafNode
, getLeafNode
, putIndexNode
, getIndexNode
, castNode
, castNode'
, castValue
) where
import Control.Applicative ((<$>), (<*>))
import Control.Monad (replicateM)
import Data.Binary (Binary(..), Put, Get)
import Data.Bits ((.|.), shiftL, shiftR)
import Data.Map (Map)
import Data.Proxy (Proxy(..))
import Data.Typeable (Typeable, typeRep, cast)
import Data.Word (Word8, Word32)
import qualified Data.Map as M
import Numeric (showHex)
import Unsafe.Coerce
import Data.BTree.Primitives
data Tree key val where
Tree :: {
treeHeight :: Height height
,
treeRootId :: Maybe (NodeId height key val)
} -> Tree key val
deriving (Typeable)
data LeafValue v = RawValue v | OverflowValue OverflowId
deriving (Eq, Show)
instance Binary v => Binary (LeafValue v) where
put (RawValue v) = put (0x00 :: Word8) >> put v
put (OverflowValue v) = put (0x01 :: Word8) >> put v
get = (get :: Get Word8) >>= \case
0x00 -> RawValue <$> get
0x01 -> OverflowValue <$> get
t -> fail $ "unknown leaf value: " ++ showHex t ""
type LeafItems k v = Map k (LeafValue v)
data Node height key val where
Idx :: { idxChildren :: Index key (NodeId height key val)
} -> Node ('S height) key val
Leaf :: { leafItems :: LeafItems key val
} -> Node 'Z key val
deriving (Typeable)
instance (Eq key, Eq val) => Eq (Node height key val) where
Leaf x == Leaf y = x == y
Idx x == Idx y = x == y
deriving instance (Show key, Show val) => Show (Node height key val)
deriving instance (Show key, Show val) => Show (Tree key val)
instance (Value k, Value v) => Value (Tree k v) where
instance Binary (Tree key val) where
put (Tree height rootId) = put height >> put rootId
get = Tree <$> get <*> get
putLeafNode :: (Binary key, Binary val) => Node 'Z key val -> Put
putLeafNode (Leaf items) = do
encodeSize $ fromIntegral (M.size items)
mapM_ put $ M.toList items
where
encodeSize :: Word32 -> Put
encodeSize s = put msb1 >> put msb2 >> put msb3
where
msb1 = fromIntegral $ s `shiftR` 16 :: Word8
msb2 = fromIntegral $ s `shiftR` 8 :: Word8
msb3 = fromIntegral s :: Word8
getLeafNode :: (Ord key, Binary key, Binary val) => Height 'Z -> Get (Node 'Z key val)
getLeafNode _ = do
v <- decodeSize <$> get
l <- replicateM (fromIntegral v) get
return $ Leaf (M.fromList l)
where
decodeSize :: (Word8, Word8, Word8) -> Word32
decodeSize (msb1, msb2, msb3) = msb1' .|. msb2' .|. msb3'
where
msb1' = (fromIntegral msb1 :: Word32) `shiftL` 16
msb2' = (fromIntegral msb2 :: Word32) `shiftL` 8
msb3' = fromIntegral msb3 :: Word32
putIndexNode :: (Binary key, Binary val) => Node ('S n) key val -> Put
putIndexNode (Idx idx) = put idx
getIndexNode :: (Binary key, Binary val) => Height ('S n) -> Get (Node ('S n) key val)
getIndexNode _ = Idx <$> get
castNode :: forall n key1 val1 height1 key2 val2 height2.
(Typeable key1, Typeable val1, Typeable key2, Typeable val2)
=> Height height1
-> Height height2
-> n height1 key1 val1
-> Maybe (n height2 key2 val2)
castNode height1 height2 n
| typeRep (Proxy :: Proxy key1) == typeRep (Proxy :: Proxy key2)
, typeRep (Proxy :: Proxy val1) == typeRep (Proxy :: Proxy val2)
, fromHeight height1 == fromHeight height2
= Just (unsafeCoerce n)
| otherwise
= Nothing
castNode' :: forall n h k v.
(Typeable k, Typeable v)
=> Height h
-> n h k v
-> Either (n 'Z k v) (n ('S h) k v)
castNode' h n
| Just v <- castNode h zeroHeight n = Left v
| otherwise = Right (unsafeCoerce n)
castValue :: (Typeable v1, Typeable v2) => v1 -> Maybe v2
castValue = cast