module Data.Text.Fusion.Size
(
Size
, exactSize
, maxSize
, unknownSize
, smaller
, larger
, toMax
, upperBound
, lowerBound
, isEmpty
) where
import Control.Exception (assert)
data Size = Exact !Int
| Max !Int
| Unknown
deriving (Eq, Show)
exactSize :: Int -> Size
exactSize n = assert (n >= 0) Exact n
maxSize :: Int -> Size
maxSize n = assert (n >= 0) Max n
unknownSize :: Size
unknownSize = Unknown
instance Num Size where
(+) = addSize
() = subtractSize
(*) = mulSize
fromInteger = f where f = Exact . fromInteger
addSize :: Size -> Size -> Size
addSize (Exact m) (Exact n) = Exact (m+n)
addSize (Exact m) (Max n) = Max (m+n)
addSize (Max m) (Exact n) = Max (m+n)
addSize (Max m) (Max n) = Max (m+n)
addSize _ _ = Unknown
subtractSize :: Size -> Size -> Size
subtractSize (Exact m) (Exact n) = Exact (max (mn) 0)
subtractSize (Exact m) (Max _) = Max m
subtractSize (Max m) (Exact n) = Max (max (mn) 0)
subtractSize a@(Max _) (Max _) = a
subtractSize a@(Max _) Unknown = a
subtractSize _ _ = Unknown
mulSize :: Size -> Size -> Size
mulSize (Exact m) (Exact n) = Exact (m*n)
mulSize (Exact m) (Max n) = Max (m*n)
mulSize (Max m) (Exact n) = Max (m*n)
mulSize (Max m) (Max n) = Max (m*n)
mulSize _ _ = Unknown
smaller :: Size -> Size -> Size
smaller (Exact m) (Exact n) = Exact (m `min` n)
smaller (Exact m) (Max n) = Max (m `min` n)
smaller (Exact m) Unknown = Max m
smaller (Max m) (Exact n) = Max (m `min` n)
smaller (Max m) (Max n) = Max (m `min` n)
smaller a@(Max _) Unknown = a
smaller Unknown (Exact n) = Max n
smaller Unknown (Max n) = Max n
smaller Unknown Unknown = Unknown
larger :: Size -> Size -> Size
larger (Exact m) (Exact n) = Exact (m `max` n)
larger a@(Exact m) b@(Max n) | m >= n = a
| otherwise = b
larger a@(Max m) b@(Exact n) | n >= m = b
| otherwise = a
larger (Max m) (Max n) = Max (m `max` n)
larger _ _ = Unknown
toMax :: Size -> Size
toMax (Exact n) = Max n
toMax a@(Max _) = a
toMax Unknown = Unknown
lowerBound :: Size -> Int
lowerBound (Exact n) = n
lowerBound _ = 0
upperBound :: Int -> Size -> Int
upperBound _ (Exact n) = n
upperBound _ (Max n) = n
upperBound k _ = k
isEmpty :: Size -> Bool
isEmpty (Exact n) = n <= 0
isEmpty (Max n) = n <= 0
isEmpty _ = False