Repository: apple/swift-nio
File: Sources/NIOTCPEchoClient/Client.swift (Swift)

Code before:
                            outboundType: String.self
                        )
                    )
                }
            }

        print("Connection(\(number)): Writing request")
        try await channel.outboundWriter.write("Hello on connection \(number)")

        for try await inboundData in channel.inboundStream {
            print("Connection(\(number)): Received response (\(inboundData))")

            // We only expect a single response so we can exit here
            break
        }
    }
}

/// A simple newline based encoder and decoder.
private final class NewlineDelimiterCoder: ByteToMessageDecoder, MessageToByteEncoder {
    typealias InboundIn = ByteBuffer
    typealias InboundOut = String

    private let newLine = "\n".utf8.first!

    init() {}

    func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {
        let readable = buffer.withUnsafeReadableBytes { $0.firstIndex(of: self.newLine) }
        if let readable = readable {
            context.fireChannelRead(self.wrapInboundOut(buffer.readString(length: readable)!))
            buffer.moveReaderIndex(forwardBy: 1)
            return .continue
        }
        return .needMoreData
    }

    func encode(data: String, out: inout ByteBuffer) throws {
        out.writeString(data)
        out.writeString("\n")
    }
}
#else
@main
struct Client {
    static func main() {
        fatalError("Requires at least Swift 5.9")
    }
}
#endif


Review comment (suggestion):
could we please not use `*Unsafe*` in the examples. `buffer.readableBytesView.firstIndex(of: UInt8(ascii: "\n"))` gives you what you need.

Code after:
                }
            }

        print("Connection(\(number)): Writing request")
        try await channel.outboundWriter.write("Hello on connection \(number)")

        for try await inboundData in channel.inboundStream {
            print("Connection(\(number)): Received response (\(inboundData))")

            // We only expect a single response so we can exit here.
            // Once, we exit out of this loop and the references to the `NIOAsyncChannel` are dropped
            // the connection is going to close itself.
            break
        }
    }
}

/// A simple newline based encoder and decoder.
private final class NewlineDelimiterCoder: ByteToMessageDecoder, MessageToByteEncoder {
    typealias InboundIn = ByteBuffer
    typealias InboundOut = String

    private let newLine = UInt8(ascii: "\n")

    init() {}

    func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {
        let readableBytes = buffer.readableBytesView

        if let firstLine = readableBytes.firstIndex(of: self.newLine).map({ readableBytes[..<$0] }) {
            buffer.moveReaderIndex(forwardBy: firstLine.count + 1)
            // Fire a read without a newline
            context.fireChannelRead(self.wrapInboundOut(String(buffer: ByteBuffer(firstLine))))
            return .continue
        } else {
            return .needMoreData
        }
    }

    func encode(data: String, out: inout ByteBuffer) throws {
        out.writeString(data)
        out.writeInteger(self.newLine)
    }
}
#else
@main
struct Client {
    static func main() {
        fatalError("Requires at least Swift 5.9")
    }
}