Подтвердить что ты не робот

Преобразование Lazy ByteString в строгий ByteString

У меня есть функция, которая принимает lazy ByteString, что я хочу иметь возвратные списки strict ByteStrings (лента должна быть перенесена в тип списка вывода).

import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
csVals :: L.ByteString -> [B.ByteString]

Я хочу сделать это по разным причинам, несколько функций лексики требует строгих ByteString s, и я могу гарантировать выведенный строгий ByteString на выходе csVal выше очень малы.

Как обойти "ограничение" ByteString без chunking их?

Update0

Я хочу взять Lazy ByteString и сделать строгий ByteString содержащий все свои данные.

4b9b3361

Ответ 1

Как и @sclv в комментариях выше, ленивая байтовая строка - это всего лишь список строгих байтов. Существует два подхода к преобразованию lazy ByteString в строгий (источник: обсуждение рассылки списка рассылки haskell о добавлении функции toStrict) - соответствующий код из потока сообщений ниже:

Во-первых, соответствующие библиотеки:

import qualified Data.ByteString               as B
import qualified Data.ByteString.Internal      as BI
import qualified Data.ByteString.Lazy          as BL
import qualified Data.ByteString.Lazy.Internal as BLI
import           Foreign.ForeignPtr
import           Foreign.Ptr

Подход 1 (то же, что и @sclv):

toStrict1 :: BL.ByteString -> B.ByteString
toStrict1 = B.concat . BL.toChunks

Подход 2:

toStrict2 :: BL.ByteString -> B.ByteString
toStrict2 BLI.Empty = B.empty
toStrict2 (BLI.Chunk c BLI.Empty) = c
toStrict2 lb = BI.unsafeCreate len $ go lb
  where
    len = BLI.foldlChunks (\l sb -> l + B.length sb) 0 lb

    go  BLI.Empty                   _   = return ()
    go (BLI.Chunk (BI.PS fp s l) r) ptr =
        withForeignPtr fp $ \p -> do
            BI.memcpy ptr (p `plusPtr` s) (fromIntegral l)
            go r (ptr `plusPtr` l)

Если производительность является проблемой, я рекомендую проверить вышеприведенный поток электронной почты. Он также имеет критериальный критерий. toStrict2 быстрее, чем toStrict1 в этих тестах.

Ответ 3

Если ленивая ByteString, о которой идет речь, равна <= максимальный размер строгой ByteString:

toStrict = fromMaybe SB.empty . listToMaybe . toChunks

toChunks делает каждый фрагмент максимально возможным (за исключением, возможно, последнего).

Если размер вашего ленивого байтаString больше, чем может быть строгий ByteString, тогда это невозможно: это то, для чего предназначены ленивые байтовые строки.

Ответ 4

Вы также можете использовать blaze-builder для создания строгой ByteString из ленивого

toStrict :: BL.ByteString -> BS.ByteString
toStrict = toByteString . fromLazyByteString

Он должен быть эффективным.

Ответ 5

Data.ByteString.Lazy.Char8 теперь имеет функции toStrict и fromStrict.