diff options
Diffstat (limited to 'src/Data/Primitive/ByteArray/Util.hs')
-rw-r--r-- | src/Data/Primitive/ByteArray/Util.hs | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/Data/Primitive/ByteArray/Util.hs b/src/Data/Primitive/ByteArray/Util.hs new file mode 100644 index 0000000..83a2e7d --- /dev/null +++ b/src/Data/Primitive/ByteArray/Util.hs | |||
@@ -0,0 +1,71 @@ | |||
1 | {-# LANGUAGE DataKinds #-} | ||
2 | {-# LANGUAGE FlexibleContexts #-} | ||
3 | {-# LANGUAGE FlexibleInstances #-} | ||
4 | {-# LANGUAGE KindSignatures #-} | ||
5 | {-# LANGUAGE MagicHash #-} | ||
6 | {-# LANGUAGE MultiParamTypeClasses #-} | ||
7 | {-# LANGUAGE ScopedTypeVariables #-} | ||
8 | {-# LANGUAGE TypeFamilies #-} | ||
9 | {-# LANGUAGE TypeOperators #-} | ||
10 | {-# LANGUAGE CPP #-} | ||
11 | module Data.Primitive.ByteArray.Util where | ||
12 | |||
13 | import GHC.Exts (Ptr(..)) | ||
14 | import GHC.TypeLits | ||
15 | import Control.Monad.Primitive | ||
16 | import qualified Data.ByteString as B | ||
17 | import qualified Data.ByteString.Unsafe as B | ||
18 | import Data.Primitive.Addr | ||
19 | import Data.Primitive.Types | ||
20 | import Data.Primitive.ByteArray | ||
21 | import Data.Word | ||
22 | import Foreign.Ptr | ||
23 | |||
24 | newtype Offset (n :: Nat) = Offset Int | ||
25 | |||
26 | offset :: KnownNat n => Offset n | ||
27 | offset = let k = Offset $ fromIntegral $ natVal k in k | ||
28 | |||
29 | (+.) :: Offset j -> Offset k -> Offset (j + k) | ||
30 | Offset j +. Offset k = Offset (j + k) | ||
31 | |||
32 | |||
33 | type family SizeOf a :: Nat | ||
34 | |||
35 | class IsMultipleOf (n::Nat) (k::Nat) | ||
36 | |||
37 | instance n ~ (q * k) => IsMultipleOf n k | ||
38 | |||
39 | writeAtByte :: ( Prim a | ||
40 | , PrimMonad m | ||
41 | #if __GLASGOW_HASKELL__ >= 802 | ||
42 | , IsMultipleOf n (SizeOf a) | ||
43 | #endif | ||
44 | ) => MutableByteArray (PrimState m) -> Offset n -> a -> m () | ||
45 | writeAtByte buf (Offset offset) a = writeByteArray buf (div offset $ (sizeOf a)) a | ||
46 | {-# INLINE writeAtByte #-} | ||
47 | |||
48 | readAtByte :: forall a m n. | ||
49 | ( Prim a | ||
50 | , PrimMonad m | ||
51 | #if __GLASGOW_HASKELL__ >= 802 | ||
52 | , IsMultipleOf n (SizeOf a) | ||
53 | #endif | ||
54 | ) => MutableByteArray (PrimState m) -> Offset n -> m a | ||
55 | readAtByte buf (Offset offset) = readByteArray buf (div offset $ (sizeOf (undefined :: a))) | ||
56 | {-# INLINE readAtByte #-} | ||
57 | |||
58 | writeStringAt :: PrimMonad m => MutableByteArray s -> Int -> B.ByteString -> m (Ptr a) | ||
59 | writeStringAt src o bsname = do | ||
60 | (p,cnt) <- unsafeIOToPrim $ B.unsafeUseAsCStringLen bsname return | ||
61 | let nptr = ptr (mutableByteArrayContents src) `plusPtr` o | ||
62 | copyAddr (adr nptr) (adr p) cnt | ||
63 | writeOffAddr (adr nptr) cnt (0 :: Word8) | ||
64 | return nptr | ||
65 | |||
66 | ptr :: Addr -> Ptr a | ||
67 | ptr (Addr a) = Ptr a | ||
68 | |||
69 | adr :: Ptr a -> Addr | ||
70 | adr (Ptr a) = Addr a | ||
71 | |||