-- |
-- Module      : Crypto.Cipher.Types.Utils
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : Stable
-- Portability : Excellent
--
-- Basic utility for cipher related stuff
module Crypto.Cipher.Types.Utils where

import Crypto.Internal.ByteArray (ByteArray)
import qualified Crypto.Internal.ByteArray as B
import Data.ByteString (ByteString)
import qualified Data.ByteString as S

-- | Chunk some input byte array into @sz byte list of byte array.
--
-- The input is held as a 'ByteString' while it is cut up, because
-- 'Crypto.Internal.ByteArray.splitAt' copies both halves whatever the type
-- underneath: cutting a block off the front that way copies the rest of the
-- message, once per block, and so the message about n/2 times.  A ByteString
-- shares instead, and only the blocks themselves are copied out.
chunk :: ByteArray b => Int -> b -> [b]
chunk :: forall b. ByteArray b => Int -> b -> [b]
chunk Int
sz b
bs = (ByteString -> b) -> [ByteString] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> b
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
B.convert (ByteString -> [ByteString]
split (b -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
B.convert b
bs :: ByteString))
  where
    split :: ByteString -> [ByteString]
split ByteString
b
        | ByteString -> Int
S.length ByteString
b Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
sz = [ByteString
b]
        | Bool
otherwise = let (ByteString
b1, ByteString
b2) = Int -> ByteString -> (ByteString, ByteString)
S.splitAt Int
sz ByteString
b in ByteString
b1 ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: ByteString -> [ByteString]
split ByteString
b2