Преобразование 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
содержащий все свои данные.
Ответы
Ответ 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 в этих тестах.
Ответ 2
Теперь пакет bytestring
экспортирует функцию toStrict
:
http://hackage.haskell.org/packages/archive/bytestring/0.10.2.0/doc/html/Data-ByteString-Lazy.html#v:toStrict
Это может быть не совсем то, что вы хотите, но оно, безусловно, отвечает на вопрос в заголовке этого сообщения:)
Ответ 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.