{-# LANGUAGE CPP #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Data.Binary.Instances.Primitive where

import Data.Binary.Orphans ()

import Control.Monad (replicateM)
import Data.Binary   (Binary, Get, Put, get, put)
import Data.Word     (Word8)

import qualified Data.Primitive as Prim

-- | @since 1.0.3
instance Binary Prim.ByteArray where
  put :: ByteArray -> Put
put ByteArray
ba = Int -> Put
forall t. Binary t => t -> Put
put Int
maxI Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> Put
go Int
0
    where
      maxI :: Int
      maxI :: Int
maxI = ByteArray -> Int
Prim.sizeofByteArray ByteArray
ba

      go :: Int -> Put
      go :: Int -> Put
go Int
i | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
maxI  = Word8 -> Put
forall t. Binary t => t -> Put
put (ByteArray -> Int -> Word8
forall a. Prim a => ByteArray -> Int -> a
Prim.indexByteArray ByteArray
ba Int
i :: Word8) Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> Put
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
           | Bool
otherwise = () -> Put
forall (m :: * -> *) a. Monad m => a -> m a
return ()

  get :: Get ByteArray
get = do
    Int
len <- Get Int
forall t. Binary t => Get t
get
    [Word8]
xs  <- Int -> Get Word8 -> Get [Word8]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
len Get Word8
forall t. Binary t => Get t
get
    ByteArray -> Get ByteArray
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> [Word8] -> ByteArray
forall a. Prim a => Int -> [a] -> ByteArray
Prim.byteArrayFromListN Int
len ([Word8]
xs :: [Word8]))