import { concreteStream, StreamInternal } from "@effect/core/stream/Stream/operations/_internal/StreamInternal" /** * Splits elements based on a predicate. * * @tsplus static effect/core/stream/Stream.Aspects split * @tsplus pipeable effect/core/stream/Stream split */ export function split(f: Predicate) { return (self: Stream): Stream> => { concreteStream(self) return new StreamInternal(self.channel >> loop(Chunk.empty(), f)) } } function splitInternal( leftovers: Chunk, input: Chunk, f: Predicate ): Channel, unknown, E, Chunk>, unknown> { const [chunk, remaining] = (leftovers + input).splitWhere(f) return chunk.isEmpty || remaining.isEmpty ? loop(chunk + remaining.drop(1), f) : Channel.write(Chunk.single(chunk)).flatMap(() => splitInternal(Chunk.empty(), remaining.drop(1), f) ) } function loop( leftovers: Chunk, f: Predicate ): Channel, unknown, E, Chunk>, unknown> { return Channel.readWith( (input: Chunk) => splitInternal(leftovers, input, f), (err) => Channel.fail(err), () => leftovers.isEmpty ? Channel.unit : leftovers.find(f).isNone() ? Channel.write(Chunk.single(leftovers)).flatMap(() => Channel.unit) : splitInternal(Chunk.empty(), leftovers, f).flatMap(() => Channel.unit) ) }