    -- | Convert between @ByteString@ and @Vector.Storable@
    -- without copying.
    module Data.Vector.Storable.ByteString
        ( -- | See also the caveats mentioned in the package's
          -- top-level documentation.
          byteStringToVector
        , vectorToByteString
        ) where

    import qualified Data.ByteString          as BS
    import qualified Data.ByteString.Internal as BS
    import qualified Data.Vector.Storable     as V

    import Foreign.Storable
    import Foreign.ForeignPtr

    sizeOfElem :: (Storable a) => V.Vector a -> Int
    sizeOfElem :: Vector a -> Int
    sizeOfElem vec :: Vector a
    vec = a -> Int
    forall a. Storable a => a -> Int
    sizeOf (a
    forall a. HasCallStack => a
    undefined a -> a -> a
    forall a. a -> a -> a
    `asTypeOf` Vector a -> a
    forall a. Storable a => Vector a -> a
    V.head Vector a
    vec)

    -- | Convert a @'BS.ByteString'@ to a @'V.Vector'@.
    --
    -- This function can produce @'Vector'@s which do not obey
    -- architectural alignment requirements.  On @x86@ this should
    -- not be an issue.
    byteStringToVector :: (Storable a) => BS.ByteString -> V.Vector a
    byteStringToVector :: ByteString -> Vector a
    byteStringToVector bs :: ByteString
    bs = Vector a
    vec where
        vec :: Vector a
    vec = ForeignPtr a -> Int -> Int -> Vector a
    forall a. Storable a => ForeignPtr a -> Int -> Int -> Vector a
    V.unsafeFromForeignPtr (ForeignPtr Word8 -> ForeignPtr a
    forall a b. ForeignPtr a -> ForeignPtr b
    castForeignPtr ForeignPtr Word8
    fptr) (Int -> Int
    scale Int
    off) (Int -> Int
    scale Int
    len)
        (fptr :: ForeignPtr Word8
    fptr, off :: Int
    off, len :: Int
    len) = ByteString -> (ForeignPtr Word8, Int, Int)
    BS.toForeignPtr ByteString
    bs
        scale :: Int -> Int
    scale = (Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Vector a -> Int
    forall a. Storable a => Vector a -> Int
    sizeOfElem Vector a
    vec)

    -- | Convert a @'V.Vector'@ to a @'BS.ByteString'@.
    vectorToByteString :: (Storable a) => V.Vector a -> BS.ByteString
    vectorToByteString :: Vector a -> ByteString
    vectorToByteString vec :: Vector a
    vec
      = ForeignPtr Word8 -> Int -> Int -> ByteString
    BS.fromForeignPtr (ForeignPtr a -> ForeignPtr Word8
    forall a b. ForeignPtr a -> ForeignPtr b
    castForeignPtr ForeignPtr a
    fptr) (Int -> Int
    scale Int
    off) (Int -> Int
    scale Int
    len) where
        (fptr :: ForeignPtr a
    fptr, off :: Int
    off, len :: Int
    len) = Vector a -> (ForeignPtr a, Int, Int)
    forall a. Storable a => Vector a -> (ForeignPtr a, Int, Int)
    V.unsafeToForeignPtr Vector a
    vec
        scale :: Int -> Int
    scale = (Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Vector a -> Int
    forall a. Storable a => Vector a -> Int
    sizeOfElem Vector a
    vec)