import Foundation /// Bound before decoding: AsyncBytes.lines can allocate an unbounded line. /// Package access so ScriptedTransport frames streams exactly as NativeHTTP does. package struct NativeStreamLines { private var buffer = Data() private var eventBytes = 0 private var afterCR = false private var firstLine = true let lineLimit: Int let eventLimit: Int package init(lineLimit: Int = 256 * 1024, eventLimit: Int = 1024 * 1024) { self.lineLimit = lineLimit self.eventLimit = eventLimit } package mutating func append(_ byte: UInt8) throws -> String? { if afterCR { afterCR = false if byte == 10 { return nil } } if byte == 10 || byte == 13 { afterCR = byte == 13 guard var line = String(data: buffer, encoding: .utf8) else { throw NativeClientError.message("The live connection returned invalid text.") } if firstLine { firstLine = false if line.hasPrefix("\u{FEFF}") { line.removeFirst() } } buffer.removeAll(keepingCapacity: true) if line.isEmpty { eventBytes = 0 } return line } guard buffer.count < lineLimit, eventBytes < eventLimit else { throw NativeClientError.message("The live update is too large. Reconnect to refresh it.") } buffer.append(byte) eventBytes += 1 return nil } }