packages feed

unwitch 2.1.0 → 2.2.0

raw patch · 19 files changed

+228/−1 lines, 19 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Unwitch.Convert.CInt: toDouble :: CInt -> Double
+ Unwitch.Convert.CInt: toFloat :: CInt -> Either Overflows Float
+ Unwitch.Convert.CInt: toInt :: CInt -> Int
+ Unwitch.Convert.CInt: toInt16 :: CInt -> Maybe Int16
+ Unwitch.Convert.CInt: toInt32 :: CInt -> Int32
+ Unwitch.Convert.CInt: toInt64 :: CInt -> Int64
+ Unwitch.Convert.CInt: toInt8 :: CInt -> Maybe Int8
+ Unwitch.Convert.CInt: toInteger :: CInt -> Integer
+ Unwitch.Convert.CInt: toNatural :: CInt -> Either Overflows Natural
+ Unwitch.Convert.CInt: toWord :: CInt -> Maybe Word
+ Unwitch.Convert.CInt: toWord16 :: CInt -> Maybe Word16
+ Unwitch.Convert.CInt: toWord32 :: CInt -> Maybe Word32
+ Unwitch.Convert.CInt: toWord64 :: CInt -> Maybe Word64
+ Unwitch.Convert.CInt: toWord8 :: CInt -> Maybe Word8
+ Unwitch.Convert.Double: toCInt :: Double -> Either ViaIntegerErrors CInt
+ Unwitch.Convert.Float: toCInt :: Float -> Either ViaIntegerErrors CInt
+ Unwitch.Convert.Int: toCInt :: Int -> Maybe CInt
+ Unwitch.Convert.Int16: toCInt :: Int16 -> CInt
+ Unwitch.Convert.Int32: toCInt :: Int32 -> CInt
+ Unwitch.Convert.Int64: toCInt :: Int64 -> Maybe CInt
+ Unwitch.Convert.Int8: toCInt :: Int8 -> CInt
+ Unwitch.Convert.Integer: toCInt :: Integer -> Maybe CInt
+ Unwitch.Convert.Natural: toCInt :: Natural -> Maybe CInt
+ Unwitch.Convert.Word: toCInt :: Word -> Maybe CInt
+ Unwitch.Convert.Word16: toCInt :: Word16 -> CInt
+ Unwitch.Convert.Word32: toCInt :: Word32 -> Maybe CInt
+ Unwitch.Convert.Word64: toCInt :: Word64 -> Maybe CInt
+ Unwitch.Convert.Word8: toCInt :: Word8 -> CInt

Files

Changelog.md view
@@ -1,5 +1,15 @@ # Change log for unwitch project +## Version 2.2.0++ New module Unwitch.Convert.CInt — conversions from CInt (Foreign.C.Types)+  to all supported numeric types (Int, Int8–64, Word, Word8–64, Integer,+  Natural, Float, Double)++ Add toCInt to all 14 existing Convert modules (Int, Int8, Int16, Int32,+  Int64, Integer, Word, Word8, Word16, Word32, Word64, Natural, Float,+  Double)++ Add CIntSpec test module with 12 tests covering total and fallible+  CInt conversions+ ## Version 2.1.0 + Add Haddock documentation to partial conversion functions across   all Convert modules — docs focus on non-obvious information only:
+ src/Unwitch/Convert/CInt.hs view
@@ -0,0 +1,83 @@+-- | Conversions from 'CInt'.+module Unwitch.Convert.CInt+  ( -- * Conversions+    toInt8+  , toInt16+  , toInt32+  , toInt64+  , toInt+  , toInteger+  , toWord8+  , toWord16+  , toWord32+  , toWord64+  , toWord+  , toNatural+  , toFloat+  , toDouble+  )+where++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 x) = Int32.toInt8 x++-- | Narrowing conversion, fails if outside Int16 range.+toInt16 :: CInt -> Maybe Int16+toInt16 (CInt x) = Int32.toInt16 x++-- | Unwrap the underlying Int32.+toInt32 :: CInt -> Int32+toInt32 (CInt x) = x++-- | Widening conversion, always succeeds.+toInt64 :: CInt -> Int64+toInt64 (CInt x) = Int32.toInt64 x++-- | Total conversion, Int is at least 32 bits wide.+toInt :: CInt -> Int+toInt (CInt x) = fromIntegral x++-- | Total conversion to Integer.+toInteger :: CInt -> Integer+toInteger (CInt x) = Int32.toInteger x++-- | Signed-to-unsigned narrowing, fails if negative or out of range.+toWord8 :: CInt -> Maybe Word8+toWord8 (CInt x) = Int32.toWord8 x++-- | Signed-to-unsigned narrowing, fails if negative or out of range.+toWord16 :: CInt -> Maybe Word16+toWord16 (CInt x) = Int32.toWord16 x++-- | Signed-to-unsigned, fails if negative.+toWord32 :: CInt -> Maybe Word32+toWord32 (CInt x) = Int32.toWord32 x++-- | Signed-to-unsigned, fails if negative.+toWord64 :: CInt -> Maybe Word64+toWord64 (CInt x) = Int32.toWord64 x++-- | Signed-to-unsigned, fails if negative.+toWord :: CInt -> Maybe Word+toWord (CInt x) = Int32.toWord x++-- | Signed-to-unsigned, returns 'Left' 'Underflow' for negative values.+toNatural :: CInt -> Either Overflows Natural+toNatural (CInt x) = Int32.toNatural x++-- | Checked conversion, fails if outside exact float integer range (+-16777215).+toFloat :: CInt -> Either Overflows Float+toFloat (CInt x) = Int32.toFloat x++-- | Total conversion, all Int32 values are exactly representable as Double.+toDouble :: CInt -> Double+toDouble (CInt x) = Int32.toDouble x
src/Unwitch/Convert/Double.hs view
@@ -15,6 +15,7 @@   , toWord64   , toWord   , toNatural+  , toCInt   , ViaIntegerErrors(..)   , IntegerErrors(..)   , RationalErrors(..)@@ -33,6 +34,7 @@ import Data.Word import Data.Int import Numeric.Natural (Natural)+import Foreign.C.Types (CInt(CInt))  -- | Lossy narrowing conversion, may lose precision. toFloat :: Double -> Float@@ -100,6 +102,10 @@   case Integer.toNatural integer of     Left err -> Left $ MkInteger $ IntegerFlow integer err     Right n -> Right n++-- | Converts via 'Integer', fails if not a whole number or out of range.+toCInt :: Double -> Either ViaIntegerErrors CInt+toCInt x = CInt <$> toInt32 x  -- | Convert via 'Integer' then narrow, combining errors. toViaInteger :: (Integer -> Maybe a) -> Double -> Either ViaIntegerErrors a
src/Unwitch/Convert/Float.hs view
@@ -14,6 +14,7 @@   , toWord64   , toWord   , toNatural+  , toCInt   , ViaIntegerErrors(..)   , IntegerErrors(..)   , RationalErrors(..)@@ -31,6 +32,7 @@ import Data.Word import Data.Int import Numeric.Natural (Natural)+import Foreign.C.Types (CInt(CInt))  toDouble :: Float -> Double toDouble = F.float2Double@@ -97,6 +99,10 @@   case Integer.toNatural integer of     Left err -> Left $ MkInteger $ IntegerFlow integer err     Right n -> Right n++-- | Converts via 'Integer', fails if not a whole number or out of range.+toCInt :: Float -> Either ViaIntegerErrors CInt+toCInt x = CInt <$> toInt32 x  -- | Convert via 'Integer' then narrow, combining errors. toViaInteger :: (Integer -> Maybe a) -> Float -> Either ViaIntegerErrors a
src/Unwitch/Convert/Int.hs view
@@ -14,6 +14,7 @@   , toNatural   , toFloat   , toDouble+  , toCInt   -- * Unboxed conversions   -- $unboxed   , toInt8#@@ -36,6 +37,7 @@ import           Data.Word import           Data.Int import           Numeric.Natural (Natural)+import           Foreign.C.Types (CInt(CInt)) import           Prelude hiding (toInteger) import           GHC.Exts (Int(..), Word(..), Float(..), Double(..),                            intToInt8#, int8ToInt#, intToInt16#, int16ToInt#,@@ -99,6 +101,10 @@   | x < -maxIntegralRepFloat -> Left Underflow   | x > maxIntegralRepFloat  -> Left Overflow   | otherwise                -> Right $ fromIntegral x++-- | Narrowing conversion via Int32, fails if outside Int32 range.+toCInt :: Int -> Maybe CInt+toCInt x = CInt <$> toInt32 x  -- | Checked conversion, fails if outside exact double integer range (+/-9007199254740991). toDouble :: Int -> Either Overflows Double
src/Unwitch/Convert/Int16.hs view
@@ -14,6 +14,7 @@   , toNatural   , toFloat   , toDouble+  , toCInt   -- * Unboxed conversions   -- $unboxed   , toInt8#@@ -31,6 +32,7 @@ import           Data.Word import           Data.Int import           Numeric.Natural (Natural)+import           Foreign.C.Types (CInt(CInt)) import           Prelude hiding (toInteger) import           GHC.Exts (Word(..), int16ToInt#, intToInt8#, int8ToInt#,                            int2Word#, word2Int#,@@ -82,6 +84,10 @@ toNatural x = if   | x < 0     -> Left Underflow   | otherwise  -> Right $ fromIntegral x++-- | Widening conversion via Int32, always succeeds.+toCInt :: Int16 -> CInt+toCInt x = CInt $ toInt32 x  toFloat :: Int16 -> Float toFloat = fromIntegral
src/Unwitch/Convert/Int32.hs view
@@ -14,6 +14,7 @@   , toNatural   , toFloat   , toDouble+  , toCInt   -- * Unboxed conversions   -- $unboxed   , toInt8#@@ -35,6 +36,7 @@ import           Data.Word import           Data.Int import           Numeric.Natural (Natural)+import           Foreign.C.Types (CInt(CInt)) import           Prelude hiding (toInteger) import           GHC.Exts (Int(..), Word(..), Float(..),                            int32ToInt#, intToInt8#, int8ToInt#,@@ -97,6 +99,10 @@   | x < -maxIntegralRepFloat -> Left Underflow   | x > maxIntegralRepFloat  -> Left Overflow   | otherwise                -> Right $ fromIntegral x++-- | Direct wrapping, CInt is a newtype over Int32.+toCInt :: Int32 -> CInt+toCInt = CInt  toDouble :: Int32 -> Double toDouble = fromIntegral
src/Unwitch/Convert/Int64.hs view
@@ -14,6 +14,7 @@   , toNatural   , toFloat   , toDouble+  , toCInt   -- * Unboxed conversions   -- $unboxed   , toInt8#@@ -37,6 +38,7 @@ import           Data.Word import           Data.Int import           Numeric.Natural (Natural)+import           Foreign.C.Types (CInt(CInt)) import           Prelude hiding (toInteger) import           GHC.Exts (Int(..), Word(..), Float(..), Double(..),                            int64ToInt#, intToInt64#,@@ -72,6 +74,10 @@  toInt :: Int64 -> Maybe Int toInt = Bits.toIntegralSized++-- | Narrowing conversion via Int32, fails if outside Int32 range.+toCInt :: Int64 -> Maybe CInt+toCInt x = CInt <$> toInt32 x  toInteger :: Int64 -> Integer toInteger = fromIntegral
src/Unwitch/Convert/Int8.hs view
@@ -14,6 +14,7 @@   , toNatural   , toFloat   , toDouble+  , toCInt   -- * Unboxed conversions   -- $unboxed   , toWord8#@@ -30,6 +31,7 @@ import           Data.Word import           Data.Int import           Numeric.Natural (Natural)+import           Foreign.C.Types (CInt(CInt)) import           Prelude hiding (toInteger) import           GHC.Exts (Word(..), int8ToInt#, int2Word#,                            wordToWord8#, wordToWord16#, wordToWord32#,@@ -79,6 +81,10 @@ toNatural x = if   | x < 0     -> Left Underflow   | otherwise  -> Right $ fromIntegral x++-- | Widening conversion via Int32, always succeeds.+toCInt :: Int8 -> CInt+toCInt x = CInt $ toInt32 x  toFloat :: Int8 -> Float toFloat = fromIntegral
src/Unwitch/Convert/Integer.hs view
@@ -14,6 +14,7 @@   , toWord32   , toWord64   , toWord+  , toCInt   -- * Unboxed conversions   -- $unboxed   , toDouble#@@ -38,6 +39,7 @@ import Data.Word import Data.Int import Numeric.Natural (Natural)+import Foreign.C.Types (CInt(CInt)) import           GHC.Exts (Int(..), Word(..), Float(..), Double(..),                            intToInt8#, int8ToInt#,                            intToInt16#, int16ToInt#,@@ -111,6 +113,10 @@  toWord :: Integer -> Maybe Word toWord = Bits.toIntegralSized++-- | Narrowing conversion via Int32, fails if outside Int32 range.+toCInt :: Integer -> Maybe CInt+toCInt x = CInt <$> toInt32 x  -- | Bounds-checked double conversion via IS/IP/IN toDouble# :: Integer -> (# Overflows | Double #)
src/Unwitch/Convert/Natural.hs view
@@ -14,6 +14,7 @@   , toInteger   , toFloat   , toDouble+  , toCInt   -- * Unboxed conversions   -- $unboxed   , toWord8#@@ -37,6 +38,7 @@ import           Data.Word import           Data.Int import           Numeric.Natural (Natural)+import           Foreign.C.Types (CInt(CInt)) import           Prelude hiding (toInteger) import           GHC.Exts (Int(..), Word(..), Float(..), Double(..),                            word2Int#,@@ -92,6 +94,10 @@  toInteger :: Natural -> Integer toInteger = fromIntegral++-- | Narrowing conversion via Int32, fails if outside Int32 range.+toCInt :: Natural -> Maybe CInt+toCInt x = CInt <$> toInt32 x  -- | Checked conversion, fails if outside exact float integer range (\u00b116777215). toFloat :: Natural -> Either Overflows Float
src/Unwitch/Convert/Word.hs view
@@ -14,6 +14,7 @@   , toInteger   , toFloat   , toDouble+  , toCInt   -- * Unboxed conversions   -- $unboxed   , toWord8#@@ -35,6 +36,7 @@ import           Data.Word import           Data.Int import           Numeric.Natural (Natural)+import           Foreign.C.Types (CInt(CInt)) import           Prelude hiding (toInteger) import           GHC.Exts (Int(..), Word(..), Float(..), Double(..),                            wordToWord8#, word8ToWord#,@@ -86,6 +88,10 @@  toInteger :: Word -> Integer toInteger = fromIntegral++-- | Narrowing conversion via Int32, fails if outside Int32 range.+toCInt :: Word -> Maybe CInt+toCInt x = CInt <$> toInt32 x  -- | Checked conversion, fails if outside exact float integer range (+-16777215). toFloat :: Word -> Either Overflows Float
src/Unwitch/Convert/Word16.hs view
@@ -14,6 +14,7 @@   , toInteger   , toFloat   , toDouble+  , toCInt   -- * Unboxed conversions   -- $unboxed   , toWord8#@@ -26,6 +27,7 @@ import           Data.Word import           Data.Int import           Numeric.Natural (Natural)+import           Foreign.C.Types (CInt(CInt)) import           Prelude hiding (toInteger) import           GHC.Exts (word16ToWord#, word2Int#,                            wordToWord8#, word8ToWord#,@@ -79,6 +81,10 @@  toDouble :: Word16 -> Double toDouble = fromIntegral++-- | Widening conversion via Int32, always succeeds.+toCInt :: Word16 -> CInt+toCInt x = CInt $ toInt32 x  -- | Unsigned narrowing, roundtrip at Word# toWord8# :: Word16 -> (# Word8 | (# #) #)
src/Unwitch/Convert/Word32.hs view
@@ -14,6 +14,7 @@   , toInteger   , toFloat   , toDouble+  , toCInt   -- * Unboxed conversions   -- $unboxed   , toWord8#@@ -33,6 +34,7 @@ import           Data.Word import           Data.Int import           Numeric.Natural (Natural)+import           Foreign.C.Types (CInt(CInt)) import           Prelude hiding (toInteger) import           GHC.Exts (Int(..), Word(..), Float(..),                            word32ToWord#, word2Int#,@@ -93,6 +95,10 @@  toDouble :: Word32 -> Double toDouble = fromIntegral++-- | Narrowing conversion via Int32, fails if outside Int32 range.+toCInt :: Word32 -> Maybe CInt+toCInt x = CInt <$> toInt32 x  -- | Unsigned narrowing, roundtrip at Word# toWord8# :: Word32 -> (# Word8 | (# #) #)
src/Unwitch/Convert/Word64.hs view
@@ -14,6 +14,7 @@   , toInteger   , toFloat   , toDouble+  , toCInt   -- * Unboxed conversions   -- $unboxed   , toWord8#@@ -36,6 +37,7 @@ import           Data.Word import           Data.Int import           Numeric.Natural (Natural)+import           Foreign.C.Types (CInt(CInt)) import           Prelude hiding (toInteger) import           GHC.Exts (Int(..), Word(..), Float(..), Double(..),                            word64ToWord#, wordToWord64#,@@ -89,6 +91,10 @@  toInteger :: Word64 -> Integer toInteger = fromIntegral++-- | Narrowing conversion via Int32, fails if outside Int32 range.+toCInt :: Word64 -> Maybe CInt+toCInt x = CInt <$> toInt32 x  -- | Checked conversion, fails with 'Overflow' if outside exact float integer range. toFloat :: Word64 -> Either Overflows Float
src/Unwitch/Convert/Word8.hs view
@@ -14,6 +14,7 @@   , toInteger   , toFloat   , toDouble+  , toCInt   -- * Unboxed conversions   -- $unboxed   , toInt8#@@ -24,6 +25,7 @@ import           Data.Word import           Data.Int import           Numeric.Natural (Natural)+import           Foreign.C.Types (CInt(CInt)) import           Prelude hiding (toInteger) import           GHC.Exts (word8ToWord#, word2Int#, intToInt8#, int8ToInt#,                            (==#))@@ -74,6 +76,10 @@  toDouble :: Word8 -> Double toDouble = fromIntegral++-- | Widening conversion via Int32, always succeeds.+toCInt :: Word8 -> CInt+toCInt x = CInt $ toInt32 x  -- | Unsigned->signed, source fits in Int#, roundtrip at Int# toInt8# :: Word8 -> (# Int8 | (# #) #)
test/Spec.hs view
@@ -1,6 +1,7 @@ module Main where  import Test.Hspec+import qualified Test.Convert.CIntSpec import qualified Test.Convert.Int8Spec import qualified Test.Convert.Int16Spec import qualified Test.Convert.Int32Spec@@ -28,6 +29,7 @@  main :: IO () main = hspec $ do+  Test.Convert.CIntSpec.spec   Test.Convert.Int8Spec.spec   Test.Convert.Int16Spec.spec   Test.Convert.Int32Spec.spec
+ test/Test/Convert/CIntSpec.hs view
@@ -0,0 +1,46 @@+module Test.Convert.CIntSpec (spec) where++import Test.Hspec+import Data.Int+import Data.Word+import Foreign.C.Types (CInt)+import qualified Unwitch.Convert.CInt as CInt++spec :: Spec+spec = describe "Unwitch.Convert.CInt" $ do++  describe "toInt8 (fallible)" $ do+    it "narrows in-range" $+      CInt.toInt8 (100 :: CInt) `shouldBe` Just (100 :: Int8)+    it "rejects out-of-range" $+      CInt.toInt8 (200 :: CInt) `shouldBe` Nothing++  describe "toInt16 (fallible)" $ do+    it "converts in-range" $+      CInt.toInt16 (1000 :: CInt) `shouldBe` Just (1000 :: Int16)+    it "rejects out-of-range" $+      CInt.toInt16 (40000 :: CInt) `shouldBe` Nothing++  describe "toInt32 (total)" $+    it "unwraps CInt" $+      CInt.toInt32 (42 :: CInt) `shouldBe` (42 :: Int32)++  describe "toInt (total)" $ do+    it "converts positive" $+      CInt.toInt (42 :: CInt) `shouldBe` (42 :: Int)+    it "converts negative" $+      CInt.toInt (-1 :: CInt) `shouldBe` (-1 :: Int)++  describe "toWord8 (fallible)" $ do+    it "rejects negative" $+      CInt.toWord8 (-1 :: CInt) `shouldBe` Nothing+    it "converts in-range" $+      CInt.toWord8 (255 :: CInt) `shouldBe` Just (255 :: Word8)+    it "rejects too large" $+      CInt.toWord8 (256 :: CInt) `shouldBe` Nothing++  describe "toDouble (total)" $ do+    it "converts positive" $+      CInt.toDouble (42 :: CInt) `shouldBe` (42.0 :: Double)+    it "converts negative" $+      CInt.toDouble (-100 :: CInt) `shouldBe` (-100.0 :: Double)
unwitch.cabal view
@@ -1,7 +1,7 @@ cabal-version:      3.0  name:           unwitch-version:        2.1.0+version:        2.2.0 homepage:       https://github.com/jappeace/unwitch#readme synopsis:  converts between primitives description: @@ -82,6 +82,7 @@   import: common-options   exposed-modules:       Unwitch.Convert.ByteString+      Unwitch.Convert.CInt       Unwitch.Convert.Char       Unwitch.Convert.Double       Unwitch.Convert.Fixed@@ -118,6 +119,7 @@   ghc-options: -threaded -rtsopts "-with-rtsopts=-N" -Wno-unused-packages   other-modules:       Test.Convert.ByteStringSpec+      Test.Convert.CIntSpec       Test.Convert.Int8Spec       Test.Convert.Int16Spec       Test.Convert.Int32Spec