Для этого вам необходимо использовать систему SequencedSink
; он использует приемник и отслеживаемое состояние для создания канала от многократного применения производителя приемника.
Созданный вами приемник оптимизирован для пошагового анализа значения one , которое будет результатом в конце последовательности каналов.
Однако, поскольку вы хотите, чтобы это было частью конвейерного конвейера, и каждый кусок входящего ByteString
мог бы или не мог бы соответствовать вашему парсеру один или несколько раз, вам нужно позаботиться о том, чтобы получить более детальный контроль процесса синтаксического анализа, передавая состояние неполного разбора между каждым применением приемника.
Предполагая, например, что ваш синтаксический анализатор анализирует [--]
или [----]
и т. Д., А T
равен Int
, обозначая количество проанализированных дефисов, вам необходимо отслеживать состояние синтаксического анализатора, как показано этим :
Input chunk Sink result - Data.Conduit.SequencedSinkResponse
[--][---] Emit Nothing [2, 3]
[---][--- Emit (Just #func) [3]
--------- Emit (Just #func) []
] Emit Nothing [12]
Stop
В этом случае я использую Maybe (ByteString -> Data.Attoparsec.ByteString.Result)
в качестве переданного состояния; другой тип данных может быть более подходящим в зависимости от ситуации.
Эта явная обработка потока необходима для поддержания конвейерной природы трубопровода; то, что канал синтаксического анализатора является «узким местом», всегда ожидает достаточного количества данных для частичного удовлетворения парсера, будет основным снижением производительности.
Реализация необходимого приемника должна быть довольно тривиальной с доступным ResourceT
интерфейсом монады.
РЕДАКТИРОВАТЬ: Простое применение приемника в цикле действительно было бы самым простым решением, но оно будет иметь несколько иные характеристики производительности, если ваш анализатор будет анализировать короткие фрагменты, которые часто оказываются на границах блоков байтов.