You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
32 lines
1.1 KiB
32 lines
1.1 KiB
import Foundation
|
|
|
|
/// A pure, testable line-buffered parser.
|
|
/// Receives arbitrary Data chunks, splits on newlines, emits complete lines via callback.
|
|
final class NDJSONLineBuffer: @unchecked Sendable {
|
|
private var buffer = ""
|
|
private let onLine: (String) -> Void
|
|
|
|
init(onLine: @escaping (String) -> Void) {
|
|
self.onLine = onLine
|
|
}
|
|
|
|
/// Append data to the internal buffer and emit every complete line (delimited by `\n`).
|
|
/// Partial lines are retained until the next `feed()` call completes them.
|
|
func feed(_ data: Data) {
|
|
guard let chunk = String(data: data, encoding: .utf8) else { return }
|
|
buffer.append(chunk)
|
|
|
|
while let newlineIndex = buffer.firstIndex(of: "\n") {
|
|
let line = String(buffer[buffer.startIndex..<newlineIndex])
|
|
buffer = String(buffer[buffer.index(after: newlineIndex)...])
|
|
if !line.isEmpty {
|
|
onLine(line)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Clear the internal buffer, discarding any incomplete line.
|
|
func reset() {
|
|
buffer = ""
|
|
}
|
|
}
|
|
|