module Data.StorableVector.Lazy.PointerPrivate where

import qualified Data.StorableVector.Pointer as VP
import qualified Data.StorableVector as V
import qualified Data.StorableVector.Base as VB

import Foreign.Storable (Storable)


data Pointer a =
   Pointer {
      forall a. Pointer a -> [Vector a]
chunks :: [VB.Vector a],
      forall a. Pointer a -> Pointer a
ptr    :: {-# UNPACK #-} !(VP.Pointer a)
   }


empty :: Storable a => Pointer a
empty :: forall a. Storable a => Pointer a
empty =
   forall a. [Vector a] -> Pointer a -> Pointer a
Pointer [] (forall a. Storable a => Vector a -> Pointer a
VP.cons forall a. Storable a => Vector a
V.empty)

{-# INLINE cons #-}
cons :: Storable a => [VB.Vector a] -> Pointer a
cons :: forall a. Storable a => [Vector a] -> Pointer a
cons [] = forall a. Storable a => Pointer a
empty
cons (Vector a
c:[Vector a]
cs) = forall a. [Vector a] -> Pointer a -> Pointer a
Pointer [Vector a]
cs (forall a. Storable a => Vector a -> Pointer a
VP.cons Vector a
c)

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

{-# INLINE switchL #-}
switchL :: Storable a =>
   b -> (a -> Pointer a -> b) -> Pointer a -> b
switchL :: forall a b.
Storable a =>
b -> (a -> Pointer a -> b) -> Pointer a -> b
switchL b
n a -> Pointer a -> b
j =
   let recourse :: Pointer a -> b
recourse Pointer a
p =
          let ct :: [Vector a]
ct = forall a. Pointer a -> [Vector a]
chunks Pointer a
p
          in  forall a b.
Storable a =>
b -> (a -> Pointer a -> b) -> Pointer a -> b
VP.switchL
                 (case [Vector a]
ct of
                    [] -> b
n
                    (Vector a
c:[Vector a]
cs) -> Pointer a -> b
recourse (forall a. [Vector a] -> Pointer a -> Pointer a
Pointer [Vector a]
cs (forall a. Storable a => Vector a -> Pointer a
VP.cons Vector a
c)))
                 (\a
a Pointer a
cp -> a -> Pointer a -> b
j a
a (forall a. [Vector a] -> Pointer a -> Pointer a
Pointer [Vector a]
ct Pointer a
cp))
                 (forall a. Pointer a -> Pointer a
ptr Pointer a
p)
   in  Pointer a -> b
recourse