{-# LANGUAGE CPP #-}{-# LANGUAGE BangPatterns #-}{-# LANGUAGE DeriveLift #-}{-# LANGUAGE StandaloneDeriving #-}{-# LANGUAGE TypeFamilies #-}{-# LANGUAGE Unsafe #-} #ifdef HS_BYTESTRING_ASSERTIONS {-# LANGUAGE PatternSynonyms #-} #endif {-# OPTIONS_HADDOCK not-home #-}-- |-- Module : Data.ByteString.Lazy.Internal-- Copyright : (c) Don Stewart 2006-2008-- (c) Duncan Coutts 2006-2011-- License : BSD-style-- Maintainer : dons00@gmail.com, duncan@community.haskell.org-- Stability : unstable-- Portability : non-portable---- A module containing semi-public 'ByteString' internals. This exposes-- the 'ByteString' representation and low level construction functions.-- Modules which extend the 'ByteString' system will need to use this module-- while ideally most users will be able to make do with the public interface-- modules.--moduleData.ByteString.Lazy.Internal(-- * The lazy @ByteString@ type and representationByteString (Empty ,Chunk ),LazyByteString ,chunk ,foldrChunks ,foldlChunks ,-- * Data type invariant and abstraction functioninvariant ,checkInvariant ,-- * Chunk allocation sizesdefaultChunkSize ,smallChunkSize ,chunkOverhead ,-- * Conversion with lists: packing and unpackingpackBytes ,packChars ,unpackBytes ,unpackChars ,-- * Conversions with strict ByteStringfromStrict ,toStrict ,)whereimportPreludehiding(concat)importqualifiedData.ByteString.Internal.Type asSimportData.Word(Word8)importForeign.Storable(Storable(sizeOf)) #if MIN_VERSION_base(4,13,0) importData.Semigroup(Semigroup(sconcat,stimes)) #else importData.Semigroup(Semigroup((<>),sconcat,stimes)) #endif importData.List.NonEmpty(NonEmpty((:|)))importControl.DeepSeq(NFData,rnf)importData.String(IsString(..))importData.Data(Data(..),mkNoRepType)importGHC.Exts(IsList(..))importqualifiedLanguage.Haskell.TH.SyntaxasTH #ifdef HS_BYTESTRING_ASSERTIONS importControl.Exception(assert) #endif -- | A space-efficient representation of a 'Word8' vector, supporting many-- efficient operations.---- A lazy 'ByteString' contains 8-bit bytes, or by using the operations-- from "Data.ByteString.Lazy.Char8" it can be interpreted as containing-- 8-bit characters.-- #ifndef HS_BYTESTRING_ASSERTIONS dataByteString =Empty |Chunk {-# UNPACK#-}!S.ByteString ByteString -- INVARIANT: The S.ByteString field of any Chunk is not empty.-- (See also the 'invariant' and 'checkInvariant' functions.)-- To make testing of this invariant convenient, we add an-- assertion to that effect when the HS_BYTESTRING_ASSERTIONS-- preprocessor macro is defined, by renaming the actual constructor-- and providing a pattern synonym that does the checking: #else dataByteString=Empty|Chunk_{-# UNPACK#-}!S.ByteStringByteStringpatternChunk::S.ByteString->ByteString->ByteStringpatternChunkccs<-Chunk_ccswhereChunkc@(S.BS_len)cs=assert(len>0)Chunk_ccs{-# COMPLETEEmpty,Chunk#-} #endif derivinginstanceTH.LiftByteString -- | Type synonym for the lazy flavour of 'ByteString'.---- @since 0.11.2.0typeLazyByteString =ByteString instanceEqByteString where== :: ByteString -> ByteString -> Bool (==)=ByteString -> ByteString -> Bool eq instanceOrdByteString wherecompare :: ByteString -> ByteString -> Ordering compare =ByteString -> ByteString -> Ordering cmp instanceSemigroupByteString where<> :: ByteString -> ByteString -> ByteString (<>)=ByteString -> ByteString -> ByteString append sconcat :: NonEmpty ByteString -> ByteString sconcat(ByteString b :|[ByteString] bs )=[ByteString] -> ByteString concat (ByteString b ByteString -> [ByteString] -> [ByteString] forall a. a -> [a] -> [a] :[ByteString] bs )stimes :: forall b. Integral b => b -> ByteString -> ByteString stimes=b -> ByteString -> ByteString forall b. Integral b => b -> ByteString -> ByteString times instanceMonoidByteString wheremempty :: ByteString mempty=ByteString Empty mappend :: ByteString -> ByteString -> ByteString mappend=ByteString -> ByteString -> ByteString forall a. Semigroup a => a -> a -> a (<>)mconcat :: [ByteString] -> ByteString mconcat=[ByteString] -> ByteString concat instanceNFDataByteString wherernf :: ByteString -> () rnfByteString Empty =()rnf(Chunk ByteString _ByteString b )=ByteString -> () forall a. NFData a => a -> () rnfByteString b instanceShowByteString whereshowsPrec :: Int -> ByteString -> ShowS showsPrec Int p ByteString ps String r =Int -> String -> ShowS forall a. Show a => Int -> a -> ShowS showsPrecInt p (ByteString -> String unpackChars ByteString ps )String r instanceReadByteString wherereadsPrec :: Int -> ReadS ByteString readsPrec Int p String str =[(String -> ByteString packChars String x ,String y )|(String x ,String y )<-Int -> ReadS String forall a. Read a => Int -> ReadS a readsPrecInt p String str ]-- | @since 0.10.12.0instanceIsListByteString wheretypeItemByteString =Word8fromList :: [Item ByteString] -> ByteString fromList=[Word8] -> ByteString [Item ByteString] -> ByteString packBytes toList :: ByteString -> [Item ByteString] toList=ByteString -> [Word8] ByteString -> [Item ByteString] unpackBytes -- | Beware: 'fromString' truncates multi-byte characters to octets.-- e.g. "枯朶に烏のとまりけり秋の暮" becomes �6k�nh~�Q��n�instanceIsStringByteString wherefromString :: String -> ByteString fromString=String -> ByteString packChars instanceDataByteString wheregfoldl :: forall (c :: * -> *). (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> ByteString -> c ByteString gfoldl forall d b. Data d => c (d -> b) -> d -> c b f forall g. g -> c g z ByteString txt =([Word8] -> ByteString) -> c ([Word8] -> ByteString) forall g. g -> c g z [Word8] -> ByteString packBytes c ([Word8] -> ByteString) -> [Word8] -> c ByteString forall d b. Data d => c (d -> b) -> d -> c b `f` ByteString -> [Word8] unpackBytes ByteString txt toConstr :: ByteString -> Constr toConstr ByteString _=String -> Constr forall a. HasCallStack => String -> a errorString "Data.ByteString.Lazy.ByteString.toConstr"gunfold :: forall (c :: * -> *). (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c ByteString gunfold forall b r. Data b => c (b -> r) -> c r _forall r. r -> c r _=String -> Constr -> c ByteString forall a. HasCallStack => String -> a errorString "Data.ByteString.Lazy.ByteString.gunfold"dataTypeOf :: ByteString -> DataType dataTypeOf ByteString _=String -> DataType mkNoRepTypeString "Data.ByteString.Lazy.ByteString"-------------------------------------------------------------------------- Packing and unpacking from listspackBytes ::[Word8]->ByteString packBytes :: [Word8] -> ByteString packBytes [Word8] cs0 =Int -> [Word8] -> ByteString packChunks Int 32[Word8] cs0 wherepackChunks :: Int -> [Word8] -> ByteString packChunks Int n [Word8] cs =caseInt -> [Word8] -> (ByteString, [Word8]) S.packUptoLenBytes Int n [Word8] cs of(ByteString bs ,[])->ByteString -> ByteString -> ByteString chunk ByteString bs ByteString Empty (ByteString bs ,[Word8] cs' )->ByteString -> ByteString -> ByteString Chunk ByteString bs (Int -> [Word8] -> ByteString packChunks (Int -> Int -> Int forall a. Ord a => a -> a -> a min(Int n Int -> Int -> Int forall a. Num a => a -> a -> a *Int 2)Int smallChunkSize )[Word8] cs' )packChars ::[Char]->ByteString packChars :: String -> ByteString packChars String cs0 =Int -> String -> ByteString packChunks Int 32String cs0 wherepackChunks :: Int -> String -> ByteString packChunks Int n String cs =caseInt -> String -> (ByteString, String) S.packUptoLenChars Int n String cs of(ByteString bs ,[])->ByteString -> ByteString -> ByteString chunk ByteString bs ByteString Empty (ByteString bs ,String cs' )->ByteString -> ByteString -> ByteString Chunk ByteString bs (Int -> String -> ByteString packChunks (Int -> Int -> Int forall a. Ord a => a -> a -> a min(Int n Int -> Int -> Int forall a. Num a => a -> a -> a *Int 2)Int smallChunkSize )String cs' )unpackBytes ::ByteString ->[Word8]unpackBytes :: ByteString -> [Word8] unpackBytes ByteString Empty =[]unpackBytes (Chunk ByteString c ByteString cs )=ByteString -> [Word8] -> [Word8] S.unpackAppendBytesLazy ByteString c (ByteString -> [Word8] unpackBytes ByteString cs )unpackChars ::ByteString ->[Char]unpackChars :: ByteString -> String unpackChars ByteString Empty =[]unpackChars (Chunk ByteString c ByteString cs )=ByteString -> ShowS S.unpackAppendCharsLazy ByteString c (ByteString -> String unpackChars ByteString cs )-------------------------------------------------------------------------- We no longer use these invariant-checking functions internally,-- preferring an assertion on `Chunk` itself, controlled by the-- HS_BYTESTRING_ASSERTIONS preprocessor macro.-- | The data type invariant:-- Every ByteString is either 'Empty' or consists of non-null-- 'S.StrictByteString's. All functions must preserve this.--invariant ::ByteString ->Boolinvariant :: ByteString -> Bool invariant ByteString Empty =Bool Trueinvariant (Chunk (S.BS ForeignPtr Word8 _Int len )ByteString cs )=Int len Int -> Int -> Bool forall a. Ord a => a -> a -> Bool >Int 0Bool -> Bool -> Bool &&ByteString -> Bool invariant ByteString cs -- | Lazily checks that the given 'ByteString' satisfies the data type's-- "no empty chunks" invariant, raising an exception in place of the-- first chunk that does not satisfy the invariant.checkInvariant ::ByteString ->ByteString checkInvariant :: ByteString -> ByteString checkInvariant ByteString Empty =ByteString Empty checkInvariant (Chunk c :: ByteString c @(S.BS ForeignPtr Word8 _Int len )ByteString cs )|Int len Int -> Int -> Bool forall a. Ord a => a -> a -> Bool >Int 0=ByteString -> ByteString -> ByteString Chunk ByteString c (ByteString -> ByteString checkInvariant ByteString cs )|Bool otherwise=String -> ByteString forall a. HasCallStack => String -> a error(String -> ByteString) -> String -> ByteString forall a b. (a -> b) -> a -> b $String "Data.ByteString.Lazy: invariant violation:"String -> ShowS forall a. [a] -> [a] -> [a] ++ByteString -> String forall a. Show a => a -> String show(ByteString -> ByteString -> ByteString Chunk ByteString c ByteString cs )-------------------------------------------------------------------------- | Smart constructor for 'Chunk'. Guarantees the data type invariant.chunk ::S.ByteString ->ByteString ->ByteString chunk :: ByteString -> ByteString -> ByteString chunk c :: ByteString c @(S.BS ForeignPtr Word8 _Int len )ByteString cs |Int len Int -> Int -> Bool forall a. Eq a => a -> a -> Bool ==Int 0=ByteString cs |Bool otherwise=ByteString -> ByteString -> ByteString Chunk ByteString c ByteString cs {-# INLINEchunk #-}-- | Consume the chunks of a lazy ByteString with a natural right fold.foldrChunks ::(S.ByteString ->a ->a )->a ->ByteString ->a foldrChunks :: forall a. (ByteString -> a -> a) -> a -> ByteString -> a foldrChunks ByteString -> a -> a f a z =ByteString -> a go wherego :: ByteString -> a go ByteString Empty =a z go (Chunk ByteString c ByteString cs )=ByteString -> a -> a f ByteString c (ByteString -> a go ByteString cs ){-# INLINEfoldrChunks #-}-- | Consume the chunks of a lazy ByteString with a strict, tail-recursive,-- accumulating left fold.foldlChunks ::(a ->S.ByteString ->a )->a ->ByteString ->a foldlChunks :: forall a. (a -> ByteString -> a) -> a -> ByteString -> a foldlChunks a -> ByteString -> a f =a -> ByteString -> a go wherego :: a -> ByteString -> a go !a a ByteString Empty =a a go !a a (Chunk ByteString c ByteString cs )=a -> ByteString -> a go (a -> ByteString -> a f a a ByteString c )ByteString cs {-# INLINEfoldlChunks #-}-------------------------------------------------------------------------- The representation uses lists of packed chunks. When we have to convert from-- a lazy list to the chunked representation, then by default we use this-- chunk size. Some functions give you more control over the chunk size.---- Measurements here:-- http://www.cse.unsw.edu.au/~dons/tmp/chunksize_v_cache.png---- indicate that a value around 0.5 to 1 x your L2 cache is best.-- The following value assumes people have something greater than 128k,-- and need to share the cache with other programs.-- | The chunk size used for I\/O. Currently set to 32k, less the memory management overheaddefaultChunkSize ::IntdefaultChunkSize :: Int defaultChunkSize =Int 32Int -> Int -> Int forall a. Num a => a -> a -> a *Int k Int -> Int -> Int forall a. Num a => a -> a -> a -Int chunkOverhead wherek :: Int k =Int 1024-- | The recommended chunk size. Currently set to 4k, less the memory management overheadsmallChunkSize ::IntsmallChunkSize :: Int smallChunkSize =Int 4Int -> Int -> Int forall a. Num a => a -> a -> a *Int k Int -> Int -> Int forall a. Num a => a -> a -> a -Int chunkOverhead wherek :: Int k =Int 1024-- | The memory management overhead. Currently this is tuned for GHC only.chunkOverhead ::IntchunkOverhead :: Int chunkOverhead =Int 2Int -> Int -> Int forall a. Num a => a -> a -> a *Int -> Int forall a. Storable a => a -> Int sizeOf(Int forall a. HasCallStack => a undefined::Int)-------------------------------------------------------------------------- Implementations for Eq, Ord and Monoid instanceseq ::ByteString ->ByteString ->Booleq :: ByteString -> ByteString -> Bool eq ByteString Empty ByteString Empty =Bool Trueeq ByteString Empty ByteString _=Bool Falseeq ByteString _ByteString Empty =Bool Falseeq (Chunk a :: ByteString a @(S.BS ForeignPtr Word8 ap Int al )ByteString as )(Chunk b :: ByteString b @(S.BS ForeignPtr Word8 bp Int bl )ByteString bs )=caseInt -> Int -> Ordering forall a. Ord a => a -> a -> Ordering compareInt al Int bl ofOrdering LT->ByteString a ByteString -> ByteString -> Bool forall a. Eq a => a -> a -> Bool ==ForeignPtr Word8 -> Int -> ByteString S.BS ForeignPtr Word8 bp Int al Bool -> Bool -> Bool &&ByteString -> ByteString -> Bool eq ByteString as (ByteString -> ByteString -> ByteString Chunk (ForeignPtr Word8 -> Int -> ByteString S.BS (ForeignPtr Word8 -> Int -> ForeignPtr Word8 forall a b. ForeignPtr a -> Int -> ForeignPtr b S.plusForeignPtrForeignPtr Word8 bp Int al )(Int bl Int -> Int -> Int forall a. Num a => a -> a -> a -Int al ))ByteString bs )Ordering EQ->ByteString a ByteString -> ByteString -> Bool forall a. Eq a => a -> a -> Bool ==ByteString b Bool -> Bool -> Bool &&ByteString -> ByteString -> Bool eq ByteString as ByteString bs Ordering GT->ForeignPtr Word8 -> Int -> ByteString S.BS ForeignPtr Word8 ap Int bl ByteString -> ByteString -> Bool forall a. Eq a => a -> a -> Bool ==ByteString b Bool -> Bool -> Bool &&ByteString -> ByteString -> Bool eq (ByteString -> ByteString -> ByteString Chunk (ForeignPtr Word8 -> Int -> ByteString S.BS (ForeignPtr Word8 -> Int -> ForeignPtr Word8 forall a b. ForeignPtr a -> Int -> ForeignPtr b S.plusForeignPtrForeignPtr Word8 ap Int bl )(Int al Int -> Int -> Int forall a. Num a => a -> a -> a -Int bl ))ByteString as )ByteString bs cmp ::ByteString ->ByteString ->Orderingcmp :: ByteString -> ByteString -> Ordering cmp ByteString Empty ByteString Empty =Ordering EQcmp ByteString Empty ByteString _=Ordering LTcmp ByteString _ByteString Empty =Ordering GTcmp (Chunk a :: ByteString a @(S.BS ForeignPtr Word8 ap Int al )ByteString as )(Chunk b :: ByteString b @(S.BS ForeignPtr Word8 bp Int bl )ByteString bs )=caseInt -> Int -> Ordering forall a. Ord a => a -> a -> Ordering compareInt al Int bl ofOrdering LT->caseByteString -> ByteString -> Ordering forall a. Ord a => a -> a -> Ordering compareByteString a (ForeignPtr Word8 -> Int -> ByteString S.BS ForeignPtr Word8 bp Int al )ofOrdering EQ->ByteString -> ByteString -> Ordering cmp ByteString as (ByteString -> ByteString -> ByteString Chunk (ForeignPtr Word8 -> Int -> ByteString S.BS (ForeignPtr Word8 -> Int -> ForeignPtr Word8 forall a b. ForeignPtr a -> Int -> ForeignPtr b S.plusForeignPtrForeignPtr Word8 bp Int al )(Int bl Int -> Int -> Int forall a. Num a => a -> a -> a -Int al ))ByteString bs )Ordering result ->Ordering result Ordering EQ->caseByteString -> ByteString -> Ordering forall a. Ord a => a -> a -> Ordering compareByteString a ByteString b ofOrdering EQ->ByteString -> ByteString -> Ordering cmp ByteString as ByteString bs Ordering result ->Ordering result Ordering GT->caseByteString -> ByteString -> Ordering forall a. Ord a => a -> a -> Ordering compare(ForeignPtr Word8 -> Int -> ByteString S.BS ForeignPtr Word8 ap Int bl )ByteString b ofOrdering EQ->ByteString -> ByteString -> Ordering cmp (ByteString -> ByteString -> ByteString Chunk (ForeignPtr Word8 -> Int -> ByteString S.BS (ForeignPtr Word8 -> Int -> ForeignPtr Word8 forall a b. ForeignPtr a -> Int -> ForeignPtr b S.plusForeignPtrForeignPtr Word8 ap Int bl )(Int al Int -> Int -> Int forall a. Num a => a -> a -> a -Int bl ))ByteString as )ByteString bs Ordering result ->Ordering result append ::ByteString ->ByteString ->ByteString append :: ByteString -> ByteString -> ByteString append ByteString xs ByteString ys =(ByteString -> ByteString -> ByteString) -> ByteString -> ByteString -> ByteString forall a. (ByteString -> a -> a) -> a -> ByteString -> a foldrChunks ByteString -> ByteString -> ByteString Chunk ByteString ys ByteString xs concat ::[ByteString ]->ByteString concat :: [ByteString] -> ByteString concat =[ByteString] -> ByteString to wherego :: ByteString -> [ByteString] -> ByteString go ByteString Empty [ByteString] css =[ByteString] -> ByteString to [ByteString] css go (Chunk ByteString c ByteString cs )[ByteString] css =ByteString -> ByteString -> ByteString Chunk ByteString c (ByteString -> [ByteString] -> ByteString go ByteString cs [ByteString] css )to :: [ByteString] -> ByteString to []=ByteString Empty to (ByteString cs :[ByteString] css )=ByteString -> [ByteString] -> ByteString go ByteString cs [ByteString] css -- | Repeats the given ByteString n times.times ::Integrala =>a ->ByteString ->ByteString times :: forall b. Integral b => b -> ByteString -> ByteString times a 0ByteString _=ByteString Empty times a n ByteString lbs0 |a n a -> a -> Bool forall a. Ord a => a -> a -> Bool <a 0=String -> ByteString forall a. HasCallStack => String -> a errorString "stimes: non-negative multiplier expected"|Bool otherwise=caseByteString lbs0 ofByteString Empty ->ByteString Empty Chunk ByteString bs ByteString lbs ->ByteString -> ByteString -> ByteString Chunk ByteString bs (ByteString -> ByteString go ByteString lbs )wherego :: ByteString -> ByteString go ByteString Empty =a -> ByteString -> ByteString forall b. Integral b => b -> ByteString -> ByteString times (a n a -> a -> a forall a. Num a => a -> a -> a -a 1)ByteString lbs0 go (Chunk ByteString c ByteString cs )=ByteString -> ByteString -> ByteString Chunk ByteString c (ByteString -> ByteString go ByteString cs )-------------------------------------------------------------------------- Conversions-- |/O(1)/ Convert a strict 'ByteString' into a lazy 'ByteString'.fromStrict ::S.ByteString ->ByteString fromStrict :: ByteString -> ByteString fromStrict (S.BS ForeignPtr Word8 _Int 0)=ByteString Empty fromStrict ByteString bs =ByteString -> ByteString -> ByteString Chunk ByteString bs ByteString Empty -- |/O(n)/ Convert a lazy 'ByteString' into a strict 'ByteString'.---- Note that this is an /expensive/ operation that forces the whole lazy-- ByteString into memory and then copies all the data. If possible, try to-- avoid converting back and forth between strict and lazy bytestrings.--toStrict ::ByteString ->S.ByteString toStrict :: ByteString -> ByteString toStrict =\ByteString cs ->ByteString -> ByteString -> ByteString goLen0 ByteString cs ByteString cs -- We pass the original [ByteString] (bss0) through as an argument through-- goLen0, goLen1, and goLen since we will need it again in goCopy. Passing-- it as an explicit argument avoids capturing it in these functions'-- closures which would result in unnecessary closure allocation.where-- It's still possible that the result is emptygoLen0 :: ByteString -> ByteString -> ByteString goLen0 ByteString _ByteString Empty =ForeignPtr Word8 -> Int -> ByteString S.BS ForeignPtr Word8 S.nullForeignPtr Int 0goLen0 ByteString cs0 (Chunk ByteString c ByteString cs )=ByteString -> ByteString -> ByteString -> ByteString goLen1 ByteString cs0 ByteString c ByteString cs -- It's still possible that the result is a single chunkgoLen1 :: ByteString -> ByteString -> ByteString -> ByteString goLen1 ByteString _ByteString bs ByteString Empty =ByteString bs goLen1 ByteString cs0 (S.BS ForeignPtr Word8 _Int bl )(Chunk (S.BS ForeignPtr Word8 _Int cl )ByteString cs )=ByteString -> Int -> ByteString -> ByteString goLen ByteString cs0 (String -> Int -> Int -> Int S.checkedAdd String "Lazy.toStrict"Int bl Int cl )ByteString cs -- General case, just find the total length we'll needgoLen :: ByteString -> Int -> ByteString -> ByteString goLen ByteString cs0 !Int total (Chunk (S.BS ForeignPtr Word8 _Int cl )ByteString cs )=ByteString -> Int -> ByteString -> ByteString goLen ByteString cs0 (String -> Int -> Int -> Int S.checkedAdd String "Lazy.toStrict"Int total Int cl )ByteString cs goLen ByteString cs0 Int total ByteString Empty =Int -> (ForeignPtr Word8 -> IO ()) -> ByteString S.unsafeCreateFp Int total ((ForeignPtr Word8 -> IO ()) -> ByteString) -> (ForeignPtr Word8 -> IO ()) -> ByteString forall a b. (a -> b) -> a -> b $\ForeignPtr Word8 ptr ->ByteString -> ForeignPtr Word8 -> IO () goCopy ByteString cs0 ForeignPtr Word8 ptr -- Copy the datagoCopy :: ByteString -> ForeignPtr Word8 -> IO () goCopy ByteString Empty !ForeignPtr Word8 _=() -> IO () forall a. a -> IO a forall (m :: * -> *) a. Monad m => a -> m a return()goCopy (Chunk (S.BS ForeignPtr Word8 _Int 0)ByteString cs )!ForeignPtr Word8 ptr =ByteString -> ForeignPtr Word8 -> IO () goCopy ByteString cs ForeignPtr Word8 ptr goCopy (Chunk (S.BS ForeignPtr Word8 fp Int len )ByteString cs )!ForeignPtr Word8 ptr =doForeignPtr Word8 -> ForeignPtr Word8 -> Int -> IO () S.memcpyFp ForeignPtr Word8 ptr ForeignPtr Word8 fp Int len ByteString -> ForeignPtr Word8 -> IO () goCopy ByteString cs (ForeignPtr Word8 ptr ForeignPtr Word8 -> Int -> ForeignPtr Word8 forall a b. ForeignPtr a -> Int -> ForeignPtr b `S.plusForeignPtr`Int len )-- See the comment on Data.ByteString.Internal.concat for some background on-- this implementation.