module Data.ByteUnits where
import Safe (lastMay)
import Numeric
data ByteUnit = Bytes | KiloBytes | MegaBytes | GigaBytes | TeraBytes | PetaBytes | ExaBytes deriving (Show, Eq)
data ByteValue = ByteValue Float ByteUnit deriving (Show, Eq)
instance Ord ByteValue where
compare a b = compare (getBytes a) (getBytes b)
getBytes :: ByteValue -> Float
getBytes (ByteValue v bu) = case bu of
Bytes -> v
KiloBytes -> v * (1024 ** 1)
MegaBytes -> v * (1024 ** 2)
GigaBytes -> v * (1024 ** 3)
TeraBytes -> v * (1024 ** 4)
PetaBytes -> v * (1024 ** 4)
ExaBytes -> v * (1024 ** 5)
convertByteUnit :: ByteValue -> ByteUnit -> ByteValue
convertByteUnit bv bu = case bu of
Bytes -> ByteValue bytes Bytes
KiloBytes -> ByteValue (bytes / (1024 ** 1)) KiloBytes
MegaBytes -> ByteValue (bytes / (1024 ** 2)) MegaBytes
GigaBytes -> ByteValue (bytes / (1024 ** 3)) GigaBytes
TeraBytes -> ByteValue (bytes / (1024 ** 4)) TeraBytes
PetaBytes -> ByteValue (bytes / (1024 ** 4)) PetaBytes
ExaBytes -> ByteValue (bytes / (1024 ** 5)) ExaBytes
where bytes = getBytes bv
getAppropriateUnits :: ByteValue -> ByteValue
getAppropriateUnits bv = do
let bUnits = [Bytes, KiloBytes, MegaBytes, GigaBytes, TeraBytes, PetaBytes, ExaBytes]
let bytes = getBytes bv
let units = fmap (\bu -> convertByteUnit (ByteValue bytes Bytes) bu) bUnits
let appropriateUnits = filter (\(ByteValue v' _) -> (v' >= 1.0)) units
case (lastMay appropriateUnits) of
Just (bv') -> bv'
Nothing -> bv
getShortHand :: ByteValue -> String
getShortHand (ByteValue v bu) = (showFFloat (Just 2) v) (" " ++buShort) where
buShort = case bu of
Bytes -> "B"
KiloBytes -> "KB"
MegaBytes -> "MB"
GigaBytes -> "GB"
TeraBytes -> "TB"
PetaBytes -> "PB"
ExaBytes -> "EB"