-- | Conversions from 'CInt'.
-- CInt is GHC-specific (wraps Int32 in GHC, Int in MicroHs),
-- so this module is only available under GHC.
module Unwitch.Convert.CInt
#ifdef __GLASGOW_HASKELL__
  ( -- * Conversions
    toInt8
  , toInt16
  , toInt32
  , toInt64
  , toInt
  , toInteger
  , toWord8
  , toWord16
  , toWord32
  , toWord64
  , toWord
  , toNatural
  , toFloat
  , toDouble
  )
#endif
where

#ifdef __GLASGOW_HASKELL__
import           Unwitch.Errors
import qualified Unwitch.Convert.Int32 as Int32
import           Data.Word
import           Data.Int
import           Numeric.Natural (Natural)
import           Prelude hiding (toInteger)
import           Foreign.C.Types (CInt(CInt))

-- | Narrowing conversion, fails if outside Int8 range.
toInt8 :: CInt -> Maybe Int8
toInt8 :: CInt -> Maybe Int8
toInt8 (CInt Int32
x) = Int32 -> Maybe Int8
Int32.toInt8 Int32
x

-- | Narrowing conversion, fails if outside Int16 range.
toInt16 :: CInt -> Maybe Int16
toInt16 :: CInt -> Maybe Int16
toInt16 (CInt Int32
x) = Int32 -> Maybe Int16
Int32.toInt16 Int32
x

-- | Unwrap the underlying Int32.
toInt32 :: CInt -> Int32
toInt32 :: CInt -> Int32
toInt32 (CInt Int32
x) = Int32
x

-- | Widening conversion, always succeeds.
toInt64 :: CInt -> Int64
toInt64 :: CInt -> Int64
toInt64 (CInt Int32
x) = Int32 -> Int64
Int32.toInt64 Int32
x

-- | Total conversion, Int is at least 32 bits wide.
toInt :: CInt -> Int
toInt :: CInt -> Int
toInt (CInt Int32
x) = Int32 -> Int
Int32.toInt Int32
x

-- | Total conversion to Integer.
toInteger :: CInt -> Integer
toInteger :: CInt -> Integer
toInteger (CInt Int32
x) = Int32 -> Integer
Int32.toInteger Int32
x

-- | Signed-to-unsigned narrowing, fails if negative or out of range.
toWord8 :: CInt -> Maybe Word8
toWord8 :: CInt -> Maybe Word8
toWord8 (CInt Int32
x) = Int32 -> Maybe Word8
Int32.toWord8 Int32
x

-- | Signed-to-unsigned narrowing, fails if negative or out of range.
toWord16 :: CInt -> Maybe Word16
toWord16 :: CInt -> Maybe Word16
toWord16 (CInt Int32
x) = Int32 -> Maybe Word16
Int32.toWord16 Int32
x

-- | Signed-to-unsigned, fails if negative.
toWord32 :: CInt -> Maybe Word32
toWord32 :: CInt -> Maybe Word32
toWord32 (CInt Int32
x) = Int32 -> Maybe Word32
Int32.toWord32 Int32
x

-- | Signed-to-unsigned, fails if negative.
toWord64 :: CInt -> Maybe Word64
toWord64 :: CInt -> Maybe Word64
toWord64 (CInt Int32
x) = Int32 -> Maybe Word64
Int32.toWord64 Int32
x

-- | Signed-to-unsigned, fails if negative.
toWord :: CInt -> Maybe Word
toWord :: CInt -> Maybe Word
toWord (CInt Int32
x) = Int32 -> Maybe Word
Int32.toWord Int32
x

-- | Signed-to-unsigned, returns 'Left' 'Underflow' for negative values.
toNatural :: CInt -> Either Overflows Natural
toNatural :: CInt -> Either Overflows Natural
toNatural (CInt Int32
x) = Int32 -> Either Overflows Natural
Int32.toNatural Int32
x

-- | Checked conversion, fails if outside exact float integer range (+-16777215).
toFloat :: CInt -> Either Overflows Float
toFloat :: CInt -> Either Overflows Float
toFloat (CInt Int32
x) = Int32 -> Either Overflows Float
Int32.toFloat Int32
x

-- | Total conversion, all Int32 values are exactly representable as Double.
toDouble :: CInt -> Double
toDouble :: CInt -> Double
toDouble (CInt Int32
x) = Int32 -> Double
Int32.toDouble Int32
x
#endif