{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE TypeApplications #-}

module Cardano.Base.Bytes (
  byteArrayToByteString,
  byteStringToByteArray,
  slice,
  splitsAt,
)
where

import Data.Array.Byte (ByteArray (..))
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Short as SBS
import Data.MemPack.Buffer (
  byteArrayFromShortByteString,
  byteArrayToShortByteString,
 )

byteArrayToByteString :: ByteArray -> ByteString
byteArrayToByteString :: ByteArray -> ByteString
byteArrayToByteString = ShortByteString -> ByteString
SBS.fromShort (ShortByteString -> ByteString)
-> (ByteArray -> ShortByteString) -> ByteArray -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteArray -> ShortByteString
byteArrayToShortByteString
{-# INLINE byteArrayToByteString #-}

byteStringToByteArray :: ByteString -> ByteArray
byteStringToByteArray :: ByteString -> ByteArray
byteStringToByteArray = ShortByteString -> ByteArray
byteArrayFromShortByteString (ShortByteString -> ByteArray)
-> (ByteString -> ShortByteString) -> ByteString -> ByteArray
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ShortByteString
SBS.toShort
{-# INLINE byteStringToByteArray #-}

slice :: Word -> Word -> ByteString -> ByteString
slice :: Word -> Word -> ByteString -> ByteString
slice Word
offset Word
size =
  Int -> ByteString -> ByteString
BS.take (forall a b. (Integral a, Num b) => a -> b
fromIntegral @Word @Int Word
size)
    (ByteString -> ByteString)
-> (ByteString -> ByteString) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ByteString -> ByteString
BS.drop (forall a b. (Integral a, Num b) => a -> b
fromIntegral @Word @Int Word
offset)

splitsAt :: [Int] -> ByteString -> [ByteString]
splitsAt :: [Int] -> ByteString -> [ByteString]
splitsAt = Int -> [Int] -> ByteString -> [ByteString]
go Int
0
  where
    go :: Int -> [Int] -> ByteString -> [ByteString]
go !Int
_ [] ByteString
bs
      | ByteString -> Bool
BS.null ByteString
bs = []
      | Bool
otherwise = [ByteString
bs]
    go !Int
off (Int
sz : [Int]
szs) ByteString
bs
      | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
sz = Int -> ByteString -> ByteString
BS.take Int
sz ByteString
bs ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: Int -> [Int] -> ByteString -> [ByteString]
go (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
sz) [Int]
szs (Int -> ByteString -> ByteString
BS.drop Int
sz ByteString
bs)
      | Bool
otherwise = []