on master help sign in
Add array casting operations for mutable arrays
01643feHarendra Kumar
src/Streamly/Internal/Data/Array/Foreign/Mut/Type.hs+57−1
@@ -44,6 +44,12 @@ module Streamly.Internal.Data.Array.Foreign.Mut.Type
44 , unsafeSnoc
44 , unsafeSnoc
45 , snoc
45 , snoc
46
46
47+ -- * Casting
48+ , cast
49+ , castUnsafe
50+ , asBytes
51+ , asPtrUnsafe
52+
47 -- * Folding
53 -- * Folding
48 , foldl'
54 , foldl'
49 , foldr
55 , foldr
@@ -108,7 +114,7 @@ import Data.Semigroup (Semigroup(..))
108#endif
114#endif
109import Data.Word (Word8)
115import Data.Word (Word8)
110import Foreign.C.Types (CSize(..), CInt(..))
116import Foreign.C.Types (CSize(..), CInt(..))
111−import Foreign.ForeignPtr (touchForeignPtr)
117+import Foreign.ForeignPtr (touchForeignPtr, castForeignPtr)
112import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
118import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
113import Foreign.Ptr (plusPtr, minusPtr, castPtr, nullPtr)
119import Foreign.Ptr (plusPtr, minusPtr, castPtr, nullPtr)
114import Foreign.Storable (Storable(..))
120import Foreign.Storable (Storable(..))
@@ -1159,6 +1165,56 @@ splitAt i arr@Array{..} =
1159 }
1165 }
1160 )
1166 )
1161
1167
1168+-------------------------------------------------------------------------------
1169+-- Casting
1170+-------------------------------------------------------------------------------
1171+
1172+-- | Cast an array having elements of type @a@ into an array having elements of
1173+-- type @b@. The array size must be a multiple of the size of type @b@
1174+-- otherwise accessing the last element of the array may result into a crash or
1175+-- a random value.
1176+--
1177+-- /Pre-release/
1178+--
1179+castUnsafe ::
1180+#ifdef DEVBUILD
1181+ Storable b =>
1182+#endif
1183+ Array a -> Array b
1184+castUnsafe (Array start end bound) =
1185+ Array (castForeignPtr start) (castPtr end) (castPtr bound)
1186+
1187+-- | Cast an @Array a@ into an @Array Word8@.
1188+--
1189+-- /Pre-release/
1190+--
1191+asBytes :: Array a -> Array Word8
1192+asBytes = castUnsafe
1193+
1194+-- | Cast an array having elements of type @a@ into an array having elements of
1195+-- type @b@. The length of the array should be a multiple of the size of the
1196+-- target element otherwise 'Nothing' is returned.
1197+--
1198+-- /Pre-release/
1199+--
1200+cast :: forall a b. Storable b => Array a -> Maybe (Array b)
1201+cast arr =
1202+ let len = byteLength arr
1203+ r = len `mod` sizeOf (undefined :: b)
1204+ in if r /= 0
1205+ then Nothing
1206+ else Just $ castUnsafe arr
1207+
1208+-- | Use an @Array a@ as @Ptr b@.
1209+--
1210+-- /Unsafe/
1211+--
1212+-- /Pre-release/
1213+--
1214+asPtrUnsafe :: Array a -> (Ptr b -> IO c) -> IO c
1215+asPtrUnsafe Array{..} act = do
1216+ unsafeWithForeignPtr aStart $ \ptr -> act (castPtr ptr)
1217+
1162-------------------------------------------------------------------------------
1218-------------------------------------------------------------------------------
1163-- Instances
1219-- Instances
1164-------------------------------------------------------------------------------
1220-------------------------------------------------------------------------------