{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}

module Data.Packed.Skippable (Skippable (..), unsafeSkipN) where

import Data.Kind
import Data.Packed.Reader
import Foreign (plusPtr)
import Foreign.Storable

class Skippable a where
    -- A function that moves the cursor at the end of the first packed value in the buffer.
    --
    -- Beware, this does not rely on `Data.Packed.FieldSize`, therefore it usually entails a traversals
    skip :: PackedReader '[a] r ()

instance (Storable a) => Skippable a where
    skip :: forall (r :: [*]). PackedReader '[a] r ()
skip = Int -> PackedReader '[a] r ()
forall (a :: [*]) (r :: [*]). Int -> PackedReader a r ()
unsafeSkipN (a -> Int
forall a. Storable a => a -> Int
sizeOf (a
forall a. HasCallStack => a
undefined :: a))

{-# INLINE unsafeSkipN #-}

-- | UNSAFE: Shifts the cursor to n bytes to the right.
unsafeSkipN :: forall (a :: [Type]) (r :: [Type]). Int -> PackedReader a r ()
unsafeSkipN :: forall (a :: [*]) (r :: [*]). Int -> PackedReader a r ()
unsafeSkipN Int
n = (ReaderPtr (a :++: r) -> Int -> IO ((), ReaderPtr (a :++: r), Int))
-> PackedReader a r ()
forall (p :: [*]) (r :: [*]) v.
(ReaderPtr (a :++: r) -> Int -> IO (v, ReaderPtr (a :++: r), Int))
-> PackedReader p r v
mkPackedReader ((ReaderPtr (a :++: r)
  -> Int -> IO ((), ReaderPtr (a :++: r), Int))
 -> PackedReader a r ())
-> (ReaderPtr (a :++: r)
    -> Int -> IO ((), ReaderPtr (a :++: r), Int))
-> PackedReader a r ()
forall a b. (a -> b) -> a -> b
$ \ReaderPtr (a :++: r)
ptr Int
l -> ((), ReaderPtr (a :++: r), Int)
-> IO ((), ReaderPtr (a :++: r), Int)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
Prelude.return ((), ReaderPtr (a :++: r)
ptr ReaderPtr (a :++: r) -> Int -> ReaderPtr (a :++: r)
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
n, Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n)