{-# LANGUAGE CPP #-}
{-# OPTIONS_GHC -fno-warn-missing-methods #-}
module Data.Text.Internal.Fusion.Size
(
Size
, exactSize
, maxSize
, betweenSize
, unknownSize
, unionSize
, charSize
, codePointsSize
, exactly
, smaller
, larger
, upperBound
, lowerBound
, compareSize
, isEmpty
) where
import Data.Char (ord)
import Data.Text.Internal (mul)
#if defined(ASSERTS)
import Control.Exception (assert)
#endif
data Size = Between {-# UNPACK #-} !Int {-# UNPACK #-} !Int
| Unknown
deriving (Size -> Size -> Bool
(Size -> Size -> Bool) -> (Size -> Size -> Bool) -> Eq Size
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Size -> Size -> Bool
$c/= :: Size -> Size -> Bool
== :: Size -> Size -> Bool
$c== :: Size -> Size -> Bool
Eq, Int -> Size -> ShowS
[Size] -> ShowS
Size -> String
(Int -> Size -> ShowS)
-> (Size -> String) -> ([Size] -> ShowS) -> Show Size
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Size] -> ShowS
$cshowList :: [Size] -> ShowS
show :: Size -> String
$cshow :: Size -> String
showsPrec :: Int -> Size -> ShowS
$cshowsPrec :: Int -> Size -> ShowS
Show)
exactly :: Size -> Maybe Int
exactly :: Size -> Maybe Int
exactly (Between na :: Int
na nb :: Int
nb) | Int
na Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
nb = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
na
exactly _ = Maybe Int
forall a. Maybe a
Nothing
{-# INLINE exactly #-}
charSize :: Char -> Size
charSize :: Char -> Size
charSize c :: Char
c
| Char -> Int
ord Char
c Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< 0x10000 = Int -> Size
exactSize 1
| Bool
otherwise = Int -> Size
exactSize 2
codePointsSize :: Int -> Size
codePointsSize :: Int -> Size
codePointsSize n :: Int
n =
#if defined(ASSERTS)
assert (n >= 0)
#endif
Int -> Int -> Size
Between Int
n (2Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
n)
{-# INLINE codePointsSize #-}
exactSize :: Int -> Size
exactSize :: Int -> Size
exactSize n :: Int
n =
#if defined(ASSERTS)
assert (n >= 0)
#endif
Int -> Int -> Size
Between Int
n Int
n
{-# INLINE exactSize #-}
maxSize :: Int -> Size
maxSize :: Int -> Size
maxSize n :: Int
n =
#if defined(ASSERTS)
assert (n >= 0)
#endif
Int -> Int -> Size
Between 0 Int
n
{-# INLINE maxSize #-}
betweenSize :: Int -> Int -> Size
betweenSize :: Int -> Int -> Size
betweenSize m :: Int
m n :: Int
n =
#if defined(ASSERTS)
assert (m >= 0)
assert (n >= m)
#endif
Int -> Int -> Size
Between Int
m Int
n
{-# INLINE betweenSize #-}
unionSize :: Size -> Size -> Size
unionSize :: Size -> Size -> Size
unionSize (Between a :: Int
a b :: Int
b) (Between c :: Int
c d :: Int
d) = Int -> Int -> Size
Between (Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
a Int
c) (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
b Int
d)
unionSize _ _ = Size
Unknown
unknownSize :: Size
unknownSize :: Size
unknownSize = Size
Unknown
{-# INLINE unknownSize #-}
instance Num Size where
+ :: Size -> Size -> Size
(+) = Size -> Size -> Size
addSize
(-) = Size -> Size -> Size
subtractSize
* :: Size -> Size -> Size
(*) = Size -> Size -> Size
mulSize
fromInteger :: Integer -> Size
fromInteger = Integer -> Size
f where f :: Integer -> Size
f = Int -> Size
exactSize (Int -> Size) -> (Integer -> Int) -> Integer -> Size
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Int
forall a. Num a => Integer -> a
fromInteger
{-# INLINE f #-}
add :: Int -> Int -> Int
add :: Int -> Int -> Int
add m :: Int
m n :: Int
n | Int
mn Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= 0 = Int
mn
| Bool
otherwise = Int
overflowError
where mn :: Int
mn = Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n
{-# INLINE add #-}
addSize :: Size -> Size -> Size
addSize :: Size -> Size -> Size
addSize (Between ma :: Int
ma mb :: Int
mb) (Between na :: Int
na nb :: Int
nb) = Int -> Int -> Size
Between (Int -> Int -> Int
add Int
ma Int
na) (Int -> Int -> Int
add Int
mb Int
nb)
addSize _ _ = Size
Unknown
{-# INLINE addSize #-}
subtractSize :: Size -> Size -> Size
subtractSize :: Size -> Size -> Size
subtractSize (Between ma :: Int
ma mb :: Int
mb) (Between na :: Int
na nb :: Int
nb) = Int -> Int -> Size
Between (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Int
maInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
nb) 0) (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Int
mbInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
na) 0)
subtractSize a :: Size
a@(Between 0 _) Unknown = Size
a
subtractSize (Between _ mb :: Int
mb) Unknown = Int -> Int -> Size
Between 0 Int
mb
subtractSize _ _ = Size
Unknown
{-# INLINE subtractSize #-}
mulSize :: Size -> Size -> Size
mulSize :: Size -> Size -> Size
mulSize (Between ma :: Int
ma mb :: Int
mb) (Between na :: Int
na nb :: Int
nb) = Int -> Int -> Size
Between (Int -> Int -> Int
mul Int
ma Int
na) (Int -> Int -> Int
mul Int
mb Int
nb)
mulSize _ _ = Size
Unknown
{-# INLINE mulSize #-}
smaller :: Size -> Size -> Size
smaller :: Size -> Size -> Size
smaller a :: Size
a@(Between ma :: Int
ma mb :: Int
mb) b :: Size
b@(Between na :: Int
na nb :: Int
nb)
| Int
mb Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
na = Size
a
| Int
nb Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
ma = Size
b
| Bool
otherwise = Int -> Int -> Size
Between (Int
ma Int -> Int -> Int
forall a. Ord a => a -> a -> a
`min` Int
na) (Int
mb Int -> Int -> Int
forall a. Ord a => a -> a -> a
`min` Int
nb)
smaller a :: Size
a@(Between 0 _) Unknown = Size
a
smaller (Between _ mb :: Int
mb) Unknown = Int -> Int -> Size
Between 0 Int
mb
smaller Unknown b :: Size
b@(Between 0 _) = Size
b
smaller Unknown (Between _ nb :: Int
nb) = Int -> Int -> Size
Between 0 Int
nb
smaller Unknown Unknown = Size
Unknown
{-# INLINE smaller #-}
larger :: Size -> Size -> Size
larger :: Size -> Size -> Size
larger a :: Size
a@(Between ma :: Int
ma mb :: Int
mb) b :: Size
b@(Between na :: Int
na nb :: Int
nb)
| Int
ma Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
nb = Size
a
| Int
na Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
mb = Size
b
| Bool
otherwise = Int -> Int -> Size
Between (Int
ma Int -> Int -> Int
forall a. Ord a => a -> a -> a
`max` Int
na) (Int
mb Int -> Int -> Int
forall a. Ord a => a -> a -> a
`max` Int
nb)
larger _ _ = Size
Unknown
{-# INLINE larger #-}
upperBound :: Int -> Size -> Int
upperBound :: Int -> Size -> Int
upperBound _ (Between _ n :: Int
n) = Int
n
upperBound k :: Int
k _ = Int
k
{-# INLINE upperBound #-}
lowerBound :: Int -> Size -> Int
lowerBound :: Int -> Size -> Int
lowerBound _ (Between n :: Int
n _) = Int
n
lowerBound k :: Int
k _ = Int
k
{-# INLINE lowerBound #-}
compareSize :: Size -> Size -> Maybe Ordering
compareSize :: Size -> Size -> Maybe Ordering
compareSize (Between ma :: Int
ma mb :: Int
mb) (Between na :: Int
na nb :: Int
nb)
| Int
mb Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
na = Ordering -> Maybe Ordering
forall a. a -> Maybe a
Just Ordering
LT
| Int
ma Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
nb = Ordering -> Maybe Ordering
forall a. a -> Maybe a
Just Ordering
GT
| Int
ma Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
mb
, Int
ma Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
na
, Int
ma Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
nb = Ordering -> Maybe Ordering
forall a. a -> Maybe a
Just Ordering
EQ
compareSize _ _ = Maybe Ordering
forall a. Maybe a
Nothing
isEmpty :: Size -> Bool
isEmpty :: Size -> Bool
isEmpty (Between _ n :: Int
n) = Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= 0
isEmpty _ = Bool
False
{-# INLINE isEmpty #-}
overflowError :: Int
overflowError :: Int
overflowError = String -> Int
forall a. HasCallStack => String -> a
error "Data.Text.Internal.Fusion.Size: size overflow"