module Data.Size.Instances
where
import qualified Data.List as L
import Data.Size.Base
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BL
import qualified Data.IntMap as IM
import qualified Data.IntSet as IS
import qualified Data.Map as M
instance Sizeable Bool where
instance Sizeable Int where
instance Sizeable Char where
instance Sizeable Double where
sizeof _ = mksize (64 `div` bitsPerWord)
statsof x = mkstats x "" (64 `div` bitsPerWord)
instance (Sizeable t1, Sizeable t2) => Sizeable (t1, t2) where
nameof (x1, x2)
= concat ["("
, nameof x1
, ","
, nameof x2
, ")"
]
sizeof (x1, x2)
= mksize 2
<>
sizeof x1 <> sizeof x2
statsof xs@(x1, x2)
= mkstats xs "" 2
<>
statsof x1 <> statsof x2
instance (Sizeable t1, Sizeable t2, Sizeable t3) =>
Sizeable (t1, t2, t3) where
nameof (x1, x2, x3)
= concat ["("
, nameof x1
, ","
, nameof x2
, ","
, nameof x3
, ")"
]
sizeof (x1, x2, x3)
= mksize 3
<>
sizeof x1 <> sizeof x2 <> sizeof x3
statsof xs@(x1, x2, x3)
= mkstats xs "" 3
<>
statsof x1 <> statsof x2 <> statsof x3
instance (Sizeable t1, Sizeable t2, Sizeable t3, Sizeable t4) =>
Sizeable (t1, t2, t3, t4) where
nameof (x1, x2, x3, x4)
= concat ["("
, nameof x1
, ","
, nameof x2
, ","
, nameof x3
, ","
, nameof x4
, ")"
]
sizeof (x1, x2, x3, x4)
= mksize 4
<>
sizeof x1 <> sizeof x2 <> sizeof x3 <> sizeof x4
statsof xs@(x1, x2, x3, x4)
= mkstats xs "" 4
<>
statsof x1 <> statsof x2 <> statsof x3 <> statsof x4
instance Sizeable a => Sizeable [a] where
nameof xs
= listTypeName (nameof (head xs))
sizeof
= mconcat . L.map sizeof
statsof xs
| null xs
= mkstats xs "[]" 0
| nameof hd `elem` ["Char", "Int", "Double", "Float", "Bool"]
= mkstats xs "[]" 0
<>
len .*. mkstats xs "(:)" 2
<>
len .*. statsof hd
| otherwise
= mkstats xs "[]" 0
<>
len .*. mkstats xs "(:)" 2
<>
(mconcat . L.map statsof $ xs)
where
hd = head xs
len = length xs
listTypeName :: String -> String
listTypeName n
| n == "Char" = "String"
| otherwise = "[" ++ n ++ "]"
instance Sizeable IS.IntSet where
sizeof s
| IS.null s
= mksize 0
| otherwise
= len .*. mksize 2
<>
(len 1) .*. mksize 4
where
len = countTips s
statsof s
| IS.null s
= mkstats s "Nil" 0
| otherwise
= len .*. mkstats s "Tip" 2
<>
(len 1) .*. mkstats s "Bin" 4
where
len = countTips s
countTips :: IS.IntSet -> Int
countTips = cnt 0 . IS.elems
where
cnt !i []
= i
cnt !i xs@(x : _)
= cnt (i + 1) $ dropWhile (\ y -> y `div` bitsPerWord == x `div` bitsPerWord) xs
instance Sizeable v => Sizeable (IM.IntMap v) where
sizeof m
| IM.null m
= mksize 0
| otherwise
= len .*. mksize 2
<>
(len 1) .*. mksize 4
where
len = IM.size m
statsof m
| IM.null m
= mkstats m "Nil" 0
| otherwise
= len .*. mkstats m "Tip" 2
<>
(len 1) .*. mkstats m "Bin" 4
<>
IM.foldr' ((<>) . statsof) mempty m
where
len = IM.size m
instance (Sizeable k, Sizeable v) => Sizeable (M.Map k v) where
sizeof m
| M.null m
= mksize 0
| otherwise
= len .*. mksize 5
<>
M.foldWithKey (\ k v st -> sizeof k <> sizeof v <> st) mempty m
where
len = M.size m
statsof m
| M.null m
= mkstats m "Tip" 0
| otherwise
= (len + 1) .*. mkstats m "Tip" 0
<>
len .*. mkstats m "Bin" 5
<>
M.foldWithKey (\ k v st -> statsof k <> statsof v <> st) mempty m
where
len = M.size m
instance Sizeable BS.ByteString where
sizeof
= mksize . (3 +) . bytesToWords . BS.length
statsof s
= mkstats s "" (dataSize . sizeof $ s)
instance Sizeable BL.ByteString where
sizeof
= mconcat . L.map sizeof' . BL.toChunks
where
sizeof' c = mksize (3 + 1 + bytesToWords (BS.length c))
statsof s
= mkstats s "" (dataSize . sizeof $ s)