module Data.ByteCountReader (sizeInBytes, sizeInBytesAssumingBase2) where
import Data.Char (toLower)
import Data.Either.Extra (eitherToMaybe)
import Data.Text (Text(), unpack)
import GHC.Float.RealFracMethods (roundDoubleInteger)
import Text.ParserCombinators.Parsec.Number (floating3)
import Text.ParserCombinators.Parsec (GenParser, many, many1, oneOf, char, parse, anyChar)
sizeInBytes :: Text -> Maybe Integer
sizeInBytes :: Text -> Maybe Integer
sizeInBytes Text
inStr = do (Double
number, [Char]
units) <- forall a b. Either a b -> Maybe b
eitherToMaybe forall a b. (a -> b) -> a -> b
$ forall s t a.
Stream s Identity t =>
Parsec s () a -> [Char] -> s -> Either ParseError a
parse forall st. GenParser Char st (Double, [Char])
bytesParser [Char]
"<>" (Text -> [Char]
unpack Text
inStr)
Double -> Integer
roundDoubleInteger forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Double
number forall a. Num a => a -> a -> a
*) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => Integer -> a
fromInteger forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Char] -> Maybe Integer
toMultiplier [Char]
units
sizeInBytesAssumingBase2 :: Text -> Maybe Integer
sizeInBytesAssumingBase2 :: Text -> Maybe Integer
sizeInBytesAssumingBase2 Text
inStr = do (Double
number, [Char]
units) <- forall a b. Either a b -> Maybe b
eitherToMaybe forall a b. (a -> b) -> a -> b
$ forall s t a.
Stream s Identity t =>
Parsec s () a -> [Char] -> s -> Either ParseError a
parse forall st. GenParser Char st (Double, [Char])
bytesParser [Char]
"<>" (Text -> [Char]
unpack Text
inStr)
Double -> Integer
roundDoubleInteger forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Double
number forall a. Num a => a -> a -> a
*) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => Integer -> a
fromInteger forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Char] -> Maybe Integer
toBase2Multiplier [Char]
units
bytesParser :: GenParser Char st (Double, String)
bytesParser :: forall st. GenParser Char st (Double, [Char])
bytesParser = do Double
num <- forall {st}. CharParser st Double
parseNumber
forall {u}. ParsecT [Char] u Identity [Char]
parseSpaces
[Char]
units <- forall {u}. ParsecT [Char] u Identity [Char]
parseUnits
forall (m :: * -> *) a. Monad m => a -> m a
return (Double
num, [Char]
units)
where parseSpaces :: ParsecT [Char] u Identity [Char]
parseSpaces = forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
' '
parseNumber :: CharParser st Double
parseNumber = forall f st. Floating f => Bool -> CharParser st f
floating3 Bool
False
parseUnits :: ParsecT [Char] u Identity [Char]
parseUnits = forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar
toMultiplier :: String -> Maybe Integer
toMultiplier :: [Char] -> Maybe Integer
toMultiplier = forall {a}. (Eq a, IsString a) => a -> Maybe Integer
mapUnits forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower
where mapUnits :: a -> Maybe Integer
mapUnits a
"b" = Integer -> Maybe Integer
_1024RaisedTo Integer
0
mapUnits a
"kb" = Integer -> Maybe Integer
_1000RaisedTo Integer
1
mapUnits a
"kib" = Integer -> Maybe Integer
_1024RaisedTo Integer
1
mapUnits a
"mb" = Integer -> Maybe Integer
_1000RaisedTo Integer
2
mapUnits a
"mib" = Integer -> Maybe Integer
_1024RaisedTo Integer
2
mapUnits a
"gb" = Integer -> Maybe Integer
_1000RaisedTo Integer
3
mapUnits a
"gib" = Integer -> Maybe Integer
_1024RaisedTo Integer
3
mapUnits a
"tb" = Integer -> Maybe Integer
_1000RaisedTo Integer
4
mapUnits a
"tib" = Integer -> Maybe Integer
_1024RaisedTo Integer
4
mapUnits a
_ = forall a. Maybe a
Nothing
_1024RaisedTo :: Integer -> Maybe Integer
_1024RaisedTo = forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer
1024 forall a b. (Num a, Integral b) => a -> b -> a
^)
_1000RaisedTo :: Integer -> Maybe Integer
_1000RaisedTo = forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer
1000 forall a b. (Num a, Integral b) => a -> b -> a
^)
toBase2Multiplier :: String -> Maybe Integer
toBase2Multiplier :: [Char] -> Maybe Integer
toBase2Multiplier = forall {a}. (Eq a, IsString a) => a -> Maybe Integer
mapUnits forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower
where mapUnits :: a -> Maybe Integer
mapUnits a
"b" = Integer -> Maybe Integer
_1024RaisedTo Integer
0
mapUnits a
"kb" = Integer -> Maybe Integer
_1024RaisedTo Integer
1
mapUnits a
"kib" = Integer -> Maybe Integer
_1024RaisedTo Integer
1
mapUnits a
"mb" = Integer -> Maybe Integer
_1024RaisedTo Integer
2
mapUnits a
"mib" = Integer -> Maybe Integer
_1024RaisedTo Integer
2
mapUnits a
"gb" = Integer -> Maybe Integer
_1024RaisedTo Integer
3
mapUnits a
"gib" = Integer -> Maybe Integer
_1024RaisedTo Integer
3
mapUnits a
"tb" = Integer -> Maybe Integer
_1024RaisedTo Integer
4
mapUnits a
"tib" = Integer -> Maybe Integer
_1024RaisedTo Integer
4
mapUnits a
_ = forall a. Maybe a
Nothing
_1024RaisedTo :: Integer -> Maybe Integer
_1024RaisedTo = forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer
1024 forall a b. (Num a, Integral b) => a -> b -> a
^)