{-# LANGUAGE PatternSynonyms #-}

module Radix.Word.Common
  ( Range (Range, ..)
  ) where

import           Radix.Word.Foundation



-- | A closed interval between two keys.
data Range = -- | Invariant: \(k_L \le k_R\).
             UnsafeRange
               {-# UNPACK #-} !Key -- ^ \(k_L\)
               {-# UNPACK #-} !Key -- ^ \(k_R\)

instance Show Range where
  showsPrec :: Int -> Range -> ShowS
showsPrec Int
d (UnsafeRange Word
kL Word
kR) =
    Bool -> ShowS -> ShowS
showParen (Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
10) (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
      String -> ShowS
showString String
"Range " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word -> ShowS
forall a. Show a => a -> ShowS
shows Word
kL
           ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
' ' ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word -> ShowS
forall a. Show a => a -> ShowS
shows Word
kR

{-# COMPLETE Range #-}
-- | Reorders endpoints to fit mathematical notation:
--   \([12, 3]\) will be converted to \([3, 12]\).
--
--   Pattern matching guarantees \(k_1 \le k_2\).
pattern Range
  :: Word  -- ^ \(k_1\)
  -> Word  -- ^ \(k_2\)
  -> Range
pattern $mRange :: forall {r}. Range -> (Word -> Word -> r) -> ((# #) -> r) -> r
$bRange :: Word -> Word -> Range
Range kL kR <- UnsafeRange kL kR
  where
    Range Word
k1 Word
k2
      | Word
k1 Word -> Word -> Bool
forall a. Ord a => a -> a -> Bool
<= Word
k2  = Word -> Word -> Range
UnsafeRange Word
k1 Word
k2
      | Bool
otherwise = Word -> Word -> Range
UnsafeRange Word
k2 Word
k1