{-# LANGUAGE CPP               #-}
{-# LANGUAGE FlexibleInstances #-}

module HaskellWorks.Data.Simd.Internal.ChunkString where

import Data.Word
import HaskellWorks.Data.ByteString
import HaskellWorks.Data.ByteString.Lazy

import qualified Data.ByteString              as BS
import qualified Data.ByteString.Lazy         as LBS
import qualified Data.Vector.Storable         as DVS
import qualified HaskellWorks.Data.ByteString as BS

newtype ChunkString = ChunkString
  { ChunkString -> [ByteString]
chunks :: [BS.ByteString]
  } deriving (ChunkString -> ChunkString -> Bool
(ChunkString -> ChunkString -> Bool)
-> (ChunkString -> ChunkString -> Bool) -> Eq ChunkString
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ChunkString -> ChunkString -> Bool
$c/= :: ChunkString -> ChunkString -> Bool
== :: ChunkString -> ChunkString -> Bool
$c== :: ChunkString -> ChunkString -> Bool
Eq, Int -> ChunkString -> ShowS
[ChunkString] -> ShowS
ChunkString -> String
(Int -> ChunkString -> ShowS)
-> (ChunkString -> String)
-> ([ChunkString] -> ShowS)
-> Show ChunkString
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ChunkString] -> ShowS
$cshowList :: [ChunkString] -> ShowS
show :: ChunkString -> String
$cshow :: ChunkString -> String
showsPrec :: Int -> ChunkString -> ShowS
$cshowsPrec :: Int -> ChunkString -> ShowS
Show)

instance ToLazyByteString ChunkString where
  toLazyByteString :: ChunkString -> ByteString
toLazyByteString (ChunkString [ByteString]
cs) = [ByteString] -> ByteString
LBS.fromChunks [ByteString]
cs

instance ToByteStrings ChunkString where
  toByteStrings :: ChunkString -> [ByteString]
toByteStrings (ChunkString [ByteString]
bss) = [ByteString]
bss

class ToChunkString a where
  toChunkString :: a -> ChunkString

instance ToChunkString LBS.ByteString where
  toChunkString :: ByteString -> ChunkString
toChunkString = [ByteString] -> ChunkString
forall a. ToChunkString a => a -> ChunkString
toChunkString ([ByteString] -> ChunkString)
-> (ByteString -> [ByteString]) -> ByteString -> ChunkString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
LBS.toChunks

instance ToChunkString [BS.ByteString] where
  toChunkString :: [ByteString] -> ChunkString
toChunkString = [ByteString] -> ChunkString
ChunkString ([ByteString] -> ChunkString)
-> ([ByteString] -> [ByteString]) -> [ByteString] -> ChunkString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [ByteString] -> [ByteString]
BS.rechunk Int
chunkSize

instance ToChunkString [DVS.Vector Word8] where
  toChunkString :: [Vector Word8] -> ChunkString
toChunkString = [ByteString] -> ChunkString
forall a. ToChunkString a => a -> ChunkString
toChunkString ([ByteString] -> ChunkString)
-> ([Vector Word8] -> [ByteString])
-> [Vector Word8]
-> ChunkString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Vector Word8 -> ByteString
forall a. ToByteString a => a -> ByteString
toByteString (Vector Word8 -> ByteString) -> [Vector Word8] -> [ByteString]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)

instance ToChunkString [DVS.Vector Word16] where
  toChunkString :: [Vector Word16] -> ChunkString
toChunkString = [ByteString] -> ChunkString
forall a. ToChunkString a => a -> ChunkString
toChunkString ([ByteString] -> ChunkString)
-> ([Vector Word16] -> [ByteString])
-> [Vector Word16]
-> ChunkString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Vector Word16 -> ByteString
forall a. ToByteString a => a -> ByteString
toByteString (Vector Word16 -> ByteString) -> [Vector Word16] -> [ByteString]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)

instance ToChunkString [DVS.Vector Word32] where
  toChunkString :: [Vector Word32] -> ChunkString
toChunkString = [ByteString] -> ChunkString
forall a. ToChunkString a => a -> ChunkString
toChunkString ([ByteString] -> ChunkString)
-> ([Vector Word32] -> [ByteString])
-> [Vector Word32]
-> ChunkString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Vector Word32 -> ByteString
forall a. ToByteString a => a -> ByteString
toByteString (Vector Word32 -> ByteString) -> [Vector Word32] -> [ByteString]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)

instance ToChunkString [DVS.Vector Word64] where
  toChunkString :: [Vector Word64] -> ChunkString
toChunkString = [ByteString] -> ChunkString
forall a. ToChunkString a => a -> ChunkString
toChunkString ([ByteString] -> ChunkString)
-> ([Vector Word64] -> [ByteString])
-> [Vector Word64]
-> ChunkString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Vector Word64 -> ByteString
forall a. ToByteString a => a -> ByteString
toByteString (Vector Word64 -> ByteString) -> [Vector Word64] -> [ByteString]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)

instance ToChunkString (DVS.Vector Word8) where
  toChunkString :: Vector Word8 -> ChunkString
toChunkString Vector Word8
v = [ByteString] -> ChunkString
forall a. ToChunkString a => a -> ChunkString
toChunkString [Vector Word8 -> ByteString
forall a. ToByteString a => a -> ByteString
toByteString Vector Word8
v]

instance ToChunkString (DVS.Vector Word16) where
  toChunkString :: Vector Word16 -> ChunkString
toChunkString Vector Word16
v = [ByteString] -> ChunkString
forall a. ToChunkString a => a -> ChunkString
toChunkString [Vector Word16 -> ByteString
forall a. ToByteString a => a -> ByteString
toByteString Vector Word16
v]

instance ToChunkString (DVS.Vector Word32) where
  toChunkString :: Vector Word32 -> ChunkString
toChunkString Vector Word32
v = [ByteString] -> ChunkString
forall a. ToChunkString a => a -> ChunkString
toChunkString [Vector Word32 -> ByteString
forall a. ToByteString a => a -> ByteString
toByteString Vector Word32
v]

instance ToChunkString (DVS.Vector Word64) where
  toChunkString :: Vector Word64 -> ChunkString
toChunkString Vector Word64
v = [ByteString] -> ChunkString
forall a. ToChunkString a => a -> ChunkString
toChunkString [Vector Word64 -> ByteString
forall a. ToByteString a => a -> ByteString
toByteString Vector Word64
v]

#if 0
instance BitWise ChunkString where
  ChunkString (a:as) .&. ChunkString (b:bs) = ChunkString (c:cs)
    where len             = end a `min` end b
          c               = toByteString $ DVS.constructN (fromIntegral len) go
          ChunkString cs  = ChunkString as .&. ChunkString bs
          go u            = let ui = end u in (a !!! ui) .&. (b !!! ui)
  ChunkString _ .&. ChunkString _ = ChunkString []
  {-# INLINE (.&.) #-}

  ChunkString (a:as) .|. ChunkString (b:bs) = ChunkString (c:cs)
    where len             = end a `min` end b
          c               = toByteString $ DVS.constructN (fromIntegral len) go
          ChunkString cs  = ChunkString as .|. ChunkString bs
          go u            = let ui = end u in (a !!! ui) .&. (b !!! ui)
  ChunkString _ .|. ChunkString _ = ChunkString []
  {-# INLINE (.|.) #-}

  ChunkString (a:as) .^. ChunkString (b:bs) = ChunkString (c:cs)
    where len             = end a `min` end b
          c               = toByteString $ DVS.constructN (fromIntegral len) go
          ChunkString cs  = ChunkString as .^. ChunkString bs
          go u            = let ui = end u in (a !!! ui) .&. (b !!! ui)
  ChunkString _ .^. ChunkString _ = ChunkString []
  {-# INLINE (.^.) #-}

  comp (ChunkString (a:as)) = ChunkString (c:cs)
    where c               = toByteString $ DVS.constructN (fromIntegral (end a)) go
          ChunkString cs  = comp (ChunkString as)
          go u            = let ui = end u in comp (a !!! ui)
  comp (ChunkString _) = ChunkString []
  {-# INLINE comp #-}

  all0s = ChunkString $ repeat $ toByteString $ DVS.replicate chunkSize (0x00 :: Word8)
  {-# INLINE all0s #-}

  all1s = ChunkString $ repeat $ toByteString $ DVS.replicate chunkSize (0xff :: Word8)
  {-# INLINE all1s #-}
#endif

chunkSize :: Int
chunkSize :: Int
chunkSize = Int
32 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
1024 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
64
{-# INLINE chunkSize #-}