{- |
In principle you can traverse through a storable vector
using repeated calls to @viewL@ or using @index@.
However this needs a bit of pointer arrangement and allocation.
This data structure should make loops optimally fast.
module Data.StorableVector.Pointer where

-- import qualified Data.StorableVector as V
import qualified Data.StorableVector.Base as VB

import qualified Foreign.ForeignPtr as FPtr
import Foreign.Marshal.Array (advancePtr, )
import Foreign.Storable (Storable, peek, )
import Foreign (Ptr, )
import qualified System.Unsafe as Unsafe

The reference to the ForeignPtr asserts,
that the array is maintained and thus is not garbage collected.
The Ptr we use for traversing would not achieve this.
{- |
We might have name the data type iterator.
data Pointer a =
   Pointer {
      fptr :: {-# UNPACK #-} !(FPtr.ForeignPtr a),
      ptr  :: {-# UNPACK #-} !(Ptr a),
      left :: {-# UNPACK #-} !Int

{-# INLINE cons #-}
cons :: Storable a => VB.Vector a -> Pointer a
cons (VB.SV fp s l) =
   Pointer fp (advancePtr (Unsafe.foreignPtrToPtr fp) s) l

{-# INLINE viewL #-}
viewL :: Storable a => Pointer a -> Maybe (a, Pointer a)
viewL = switchL Nothing (curry Just)

{-# INLINE switchL #-}
switchL :: Storable a =>
   b -> (a -> Pointer a -> b) -> Pointer a -> b
switchL n j (Pointer fp p l) =
   if l<=0
     then n
     else j (VB.inlinePerformIO (peek p)) (Pointer fp (advancePtr p 1) (l-1))
-- Unsafe.performIO at this place would make SpeedPointer test 0.5 s slower