{-# LANGUAGE CPP, PatternGuards #-}
{-# 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 Int
na 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 Size
_ = Maybe Int
forall a. Maybe a
Nothing
{-# INLINE exactly #-}
charSize :: Char -> Size
charSize :: Char -> Size
charSize Char
c
| Char -> Int
ord Char
c Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0x10000 = Int -> Size
exactSize Int
1
| Bool
otherwise = Int -> Size
exactSize Int
2
codePointsSize :: Int -> Size
codePointsSize :: Int -> Size
codePointsSize Int
n =
#if defined(ASSERTS)
assert (n >= 0)
#endif
Int -> Int -> Size
Between Int
n (Int
2Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
n)
{-# INLINE codePointsSize #-}
exactSize :: Int -> Size
exactSize :: Int -> Size
exactSize 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 Int
n =
#if defined(ASSERTS)
assert (n >= 0)
#endif
Int -> Int -> Size
Between Int
0 Int
n
{-# INLINE maxSize #-}
betweenSize :: Int -> Int -> Size
betweenSize :: Int -> Int -> Size
betweenSize Int
m 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 Int
a Int
b) (Between Int
c 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
_ Size
_ = 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 Int
m Int
n | Int
mn Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
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 Int
ma Int
mb) (Between Int
na Int
nb) = Int -> Int -> Size
Between (Int -> Int -> Int
add Int
ma Int
na) (Int -> Int -> Int
add Int
mb Int
nb)
addSize Size
_ Size
_ = Size
Unknown
{-# INLINE addSize #-}
subtractSize :: Size -> Size -> Size
subtractSize :: Size -> Size -> Size
subtractSize (Between Int
ma Int
mb) (Between Int
na 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) Int
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) Int
0)
subtractSize a :: Size
a@(Between Int
0 Int
_) Size
Unknown = Size
a
subtractSize (Between Int
_ Int
mb) Size
Unknown = Int -> Int -> Size
Between Int
0 Int
mb
subtractSize Size
_ Size
_ = Size
Unknown
{-# INLINE subtractSize #-}
mulSize :: Size -> Size -> Size
mulSize :: Size -> Size -> Size
mulSize (Between Int
ma Int
mb) (Between Int
na Int
nb) = Int -> Int -> Size
Between (Int -> Int -> Int
mul Int
ma Int
na) (Int -> Int -> Int
mul Int
mb Int
nb)
mulSize Size
_ Size
_ = Size
Unknown
{-# INLINE mulSize #-}
smaller :: Size -> Size -> Size
smaller :: Size -> Size -> Size
smaller a :: Size
a@(Between Int
ma Int
mb) b :: Size
b@(Between Int
na 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 Int
0 Int
_) Size
Unknown = Size
a
smaller (Between Int
_ Int
mb) Size
Unknown = Int -> Int -> Size
Between Int
0 Int
mb
smaller Size
Unknown b :: Size
b@(Between Int
0 Int
_) = Size
b
smaller Size
Unknown (Between Int
_ Int
nb) = Int -> Int -> Size
Between Int
0 Int
nb
smaller Size
Unknown Size
Unknown = Size
Unknown
{-# INLINE smaller #-}
larger :: Size -> Size -> Size
larger :: Size -> Size -> Size
larger a :: Size
a@(Between Int
ma Int
mb) b :: Size
b@(Between Int
na 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
_ Size
_ = Size
Unknown
{-# INLINE larger #-}
upperBound :: Int -> Size -> Int
upperBound :: Int -> Size -> Int
upperBound Int
_ (Between Int
_ Int
n) = Int
n
upperBound Int
k Size
_ = Int
k
{-# INLINE upperBound #-}
lowerBound :: Int -> Size -> Int
lowerBound :: Int -> Size -> Int
lowerBound Int
_ (Between Int
n Int
_) = Int
n
lowerBound Int
k Size
_ = Int
k
{-# INLINE lowerBound #-}
compareSize :: Size -> Size -> Maybe Ordering
compareSize :: Size -> Size -> Maybe Ordering
compareSize (Between Int
ma Int
mb) (Between Int
na 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 Size
_ Size
_ = Maybe Ordering
forall a. Maybe a
Nothing
isEmpty :: Size -> Bool
isEmpty :: Size -> Bool
isEmpty (Between Int
_ Int
n) = Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0
isEmpty Size
_ = Bool
False
{-# INLINE isEmpty #-}
overflowError :: Int
overflowError :: Int
overflowError = String -> Int
forall a. HasCallStack => String -> a
error String
"Data.Text.Internal.Fusion.Size: size overflow"