{-# LANGUAGE GADTs      #-}
{-# LANGUAGE RankNTypes #-}

module HaskellWorks.Data.Json.Simd.Internal.Index.Simple where

import Control.Monad.ST
import Data.Word
import Foreign

import qualified Data.Vector.Storable.Mutable                 as DVSM
import qualified Foreign                                      as F
import qualified Foreign.ForeignPtr.Unsafe                    as F
import qualified HaskellWorks.Data.Json.Simd.Internal.Foreign as F

{- HLINT ignore "Reduce duplication"  -}
{- HLINT ignore "Redundant do"        -}

data WorkBuffers = WorkBuffers
  { WorkBuffers -> ForeignPtr UInt8
workBuffersP :: !(ForeignPtr F.UInt8)
  , WorkBuffers -> Ptr UInt8
workBuffersD :: !(Ptr F.UInt8)
  , WorkBuffers -> Ptr UInt8
workBuffersA :: !(Ptr F.UInt8)
  , WorkBuffers -> Ptr UInt8
workBuffersZ :: !(Ptr F.UInt8)
  , WorkBuffers -> Ptr UInt8
workBuffersQ :: !(Ptr F.UInt8)
  , WorkBuffers -> Ptr UInt8
workBuffersB :: !(Ptr F.UInt8)
  , WorkBuffers -> Ptr UInt8
workBuffersE :: !(Ptr F.UInt8)
  }

data WorkState = WorkState
  { WorkState -> Ptr Size
workStateZ :: !(Ptr F.Size)
  , WorkState -> Ptr Size
workStateO :: !(Ptr F.Size)
  , WorkState -> Ptr Size
workStateE :: !(Ptr F.Size)
  , WorkState -> Ptr Size
workStateM :: !(Ptr F.UInt64)
  , WorkState -> ForeignPtr Word8
workStateP :: !(ForeignPtr Word8)
  }

newtype BpState = BpState
  { BpState -> ForeignPtr Word8
bpStateP :: ForeignPtr Word8
  }

data Step where
  Step :: ( forall s
            .   BpState
            ->  DVSM.MVector s Word64
            ->  ST s Int)
          -> Int
          -> Step

emptyBpState :: IO BpState
emptyBpState :: IO BpState
emptyBpState = do
  ForeignPtr Any
fptr <- forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes Int
32
  forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignPtr Word8 -> BpState
BpState (forall a b. ForeignPtr a -> ForeignPtr b
F.castForeignPtr ForeignPtr Any
fptr))

allocWorkBuffers :: Int -> IO WorkBuffers
allocWorkBuffers :: Int -> IO WorkBuffers
allocWorkBuffers Int
n = do
  ForeignPtr UInt8
fptr <- forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes (Int
6 forall a. Num a => a -> a -> a
* Int
n)
  let ptr :: Ptr UInt8
ptr = forall a. ForeignPtr a -> Ptr a
F.unsafeForeignPtrToPtr ForeignPtr UInt8
fptr
  forall (m :: * -> *) a. Monad m => a -> m a
return WorkBuffers
    { workBuffersP :: ForeignPtr UInt8
workBuffersP = ForeignPtr UInt8
fptr
    , workBuffersD :: Ptr UInt8
workBuffersD = Ptr UInt8
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr`  Int
0
    , workBuffersA :: Ptr UInt8
workBuffersA = Ptr UInt8
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr`  Int
n
    , workBuffersZ :: Ptr UInt8
workBuffersZ = Ptr UInt8
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` (Int
n forall a. Num a => a -> a -> a
* Int
2)
    , workBuffersQ :: Ptr UInt8
workBuffersQ = Ptr UInt8
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` (Int
n forall a. Num a => a -> a -> a
* Int
3)
    , workBuffersB :: Ptr UInt8
workBuffersB = Ptr UInt8
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` (Int
n forall a. Num a => a -> a -> a
* Int
4)
    , workBuffersE :: Ptr UInt8
workBuffersE = Ptr UInt8
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` (Int
n forall a. Num a => a -> a -> a
* Int
5)
    }

allocWorkState :: IO WorkState
allocWorkState :: IO WorkState
allocWorkState = do
  ForeignPtr Word8
fptr <- forall a. Int -> IO (ForeignPtr a)
F.mallocForeignPtrBytes Int
256
  let ptr :: Ptr Word8
ptr = forall a. ForeignPtr a -> Ptr a
F.unsafeForeignPtrToPtr ForeignPtr Word8
fptr
  let ws :: WorkState
ws = WorkState
        { workStateZ :: Ptr Size
workStateZ = Ptr Word8
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr`  Int
0
        , workStateO :: Ptr Size
workStateO = Ptr Word8
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr`  Int
8
        , workStateE :: Ptr Size
workStateE = Ptr Word8
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` (Int
8 forall a. Num a => a -> a -> a
* Int
2)
        , workStateM :: Ptr Size
workStateM = Ptr Word8
ptr forall a b. Ptr a -> Int -> Ptr b
`F.plusPtr` (Int
8 forall a. Num a => a -> a -> a
* Int
3)
        , workStateP :: ForeignPtr Word8
workStateP = ForeignPtr Word8
fptr
        }
  forall a. Storable a => Ptr a -> a -> IO ()
F.poke (WorkState -> Ptr Size
workStateZ WorkState
ws) Size
0
  forall a. Storable a => Ptr a -> a -> IO ()
F.poke (WorkState -> Ptr Size
workStateO WorkState
ws) Size
0
  forall a. Storable a => Ptr a -> a -> IO ()
F.poke (WorkState -> Ptr Size
workStateE WorkState
ws) Size
1
  forall a. Storable a => Ptr a -> a -> IO ()
F.poke (WorkState -> Ptr Size
workStateM WorkState
ws) Size
0
  forall (m :: * -> *) a. Monad m => a -> m a
return WorkState
ws