{-# LANGUAGE TupleSections #-}
{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures, TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleContexts, FlexibleInstances, UndecidableInstances #-}
{-# LANGUAGE DefaultSignatures #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Gpu.Vulkan.Pipeline.VertexInputState.BindingOffset (BindingOffsetNew(..)) where

import GHC.Generics
import Foreign.Storable
import Control.Arrow
import Data.Kind

type Offset = Int

class BindingOffsetNew (ts :: [Type]) (a :: Type) where
	bindingOffsetNew :: (Int, Offset)

instance BindingOffsetNew' (Rep t) ts a => BindingOffsetNew (t ': ts) a where
	bindingOffsetNew :: (Int, Int)
bindingOffsetNew = forall (t :: * -> *) (ts :: [*]) a.
BindingOffsetNew' t ts a =>
Int -> (Int, Int)
bindingOffsetNew' @(Rep t) @ts @a Int
0

class BindingOffsetNew' (t :: Type -> Type) (ts :: [Type]) (a :: Type) where
	bindingOffsetNew' :: Offset -> (Int, Offset)

instance BindingOffsetNew' body ts a =>
	BindingOffsetNew' (M1 _i _c body) ts a where
	bindingOffsetNew' :: Int -> (Int, Int)
bindingOffsetNew' = forall (t :: * -> *) (ts :: [*]) a.
BindingOffsetNew' t ts a =>
Int -> (Int, Int)
bindingOffsetNew' @body @ts @a

instance Storable a => BindingOffsetNew' (K1 _i a) ts a where
	bindingOffsetNew' :: Int -> (Int, Int)
bindingOffsetNew' = (Int
0 ,) (Int -> (Int, Int)) -> (Int -> Int) -> Int -> (Int, Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall t. Storable t => Int -> Int
align @a

instance {-# OVERLAPPABLE #-} BindingOffsetNew ts a =>
	BindingOffsetNew' (K1 _i t) ts a where
	bindingOffsetNew' :: Int -> (Int, Int)
bindingOffsetNew' Int
_ = (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (Int -> Int) -> (Int, Int) -> (Int, Int)
forall b c d. (b -> c) -> (b, d) -> (c, d)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
`first` forall (ts :: [*]) a. BindingOffsetNew ts a => (Int, Int)
bindingOffsetNew @ts @a

instance BindingOffsetNew' (body :*: bs) ts a =>
	BindingOffsetNew' (M1 _i _c body :*: bs) ts a where
	bindingOffsetNew' :: Int -> (Int, Int)
bindingOffsetNew' = forall (t :: * -> *) (ts :: [*]) a.
BindingOffsetNew' t ts a =>
Int -> (Int, Int)
bindingOffsetNew' @(body :*: bs) @ts @a

instance Storable a => BindingOffsetNew' (K1 _i a :*: _bs) ts a where
	bindingOffsetNew' :: Int -> (Int, Int)
bindingOffsetNew' = (Int
0 ,) (Int -> (Int, Int)) -> (Int -> Int) -> Int -> (Int, Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall t. Storable t => Int -> Int
align @a

instance BindingOffsetNew' (b :*: (b' :*: bs)) ts a =>
	BindingOffsetNew' ((b :*: b') :*: bs) ts a where
	bindingOffsetNew' :: Int -> (Int, Int)
bindingOffsetNew' = forall (t :: * -> *) (ts :: [*]) a.
BindingOffsetNew' t ts a =>
Int -> (Int, Int)
bindingOffsetNew' @(b :*: (b' :*: bs)) @ts @a

instance {-# OVERLAPPABLE #-} (Storable t, BindingOffsetNew' bs ts a) =>
	BindingOffsetNew' (K1 _i t :*: bs) ts a where
	bindingOffsetNew' :: Int -> (Int, Int)
bindingOffsetNew' Int
ofst = forall (t :: * -> *) (ts :: [*]) a.
BindingOffsetNew' t ts a =>
Int -> (Int, Int)
bindingOffsetNew' @bs @ts @a (forall t. Storable t => Int -> Int
nextEnd @t Int
ofst)

nextEnd :: forall t . Storable t => Offset -> Offset
nextEnd :: forall t. Storable t => Int -> Int
nextEnd Int
ofst = forall t. Storable t => Int -> Int
align @t Int
ofst Int -> Int -> Int
forall a. Num a => a -> a -> a
+ forall a. Storable a => a -> Int
sizeOf @t t
forall a. HasCallStack => a
undefined

align :: forall t . Storable t => Offset -> Offset
align :: forall t. Storable t => Int -> Int
align Int
ofst = ((Int
ofst Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
algn Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
algn
	where algn :: Int
algn = forall a. Storable a => a -> Int
alignment @t t
forall a. HasCallStack => a
undefined