@@ -13,7 +13,7 @@ class CodeiumLanguageServer: CodeiumLSP {
1313 let managerDirectoryURL : URL
1414 let supportURL : URL
1515 let process : Process
16- let transport : StdioDataTransport
16+ let transport : IOTransport
1717 var terminationHandler : ( ( ) -> Void ) ?
1818 var launchHandler : ( ( ) -> Void ) ?
1919 var port : String ?
@@ -31,7 +31,7 @@ class CodeiumLanguageServer: CodeiumLSP {
3131 self . terminationHandler = terminationHandler
3232 self . launchHandler = launchHandler
3333 process = Process ( )
34- transport = StdioDataTransport ( )
34+ transport = IOTransport ( )
3535
3636 process. standardInput = transport. stdinPipe
3737 process. standardOutput = transport. stdoutPipe
@@ -141,3 +141,96 @@ class CodeiumLanguageServer: CodeiumLSP {
141141 }
142142}
143143
144+ final class IOTransport {
145+ public let stdinPipe : Pipe
146+ public let stdoutPipe : Pipe
147+ public let stderrPipe : Pipe
148+ private var closed : Bool
149+ private var queue : DispatchQueue
150+
151+ public init ( ) {
152+ stdinPipe = Pipe ( )
153+ stdoutPipe = Pipe ( )
154+ stderrPipe = Pipe ( )
155+ closed = false
156+ queue = DispatchQueue ( label: " com.intii.CopilotForXcode.IOTransport " )
157+
158+ setupFileHandleHandlers ( )
159+ }
160+
161+ public func write( _ data: Data ) {
162+ if closed {
163+ return
164+ }
165+
166+ let fileHandle = stdinPipe. fileHandleForWriting
167+
168+ queue. async {
169+ fileHandle. write ( data)
170+ }
171+ }
172+
173+ public func close( ) {
174+ queue. sync {
175+ if self . closed {
176+ return
177+ }
178+
179+ self . closed = true
180+
181+ [ stdoutPipe, stderrPipe, stdinPipe] . forEach { pipe in
182+ pipe. fileHandleForWriting. closeFile ( )
183+ pipe. fileHandleForReading. closeFile ( )
184+ }
185+ }
186+ }
187+
188+ private func setupFileHandleHandlers( ) {
189+ stdoutPipe. fileHandleForReading. readabilityHandler = { [ unowned self] handle in
190+ let data = handle. availableData
191+
192+ guard !data. isEmpty else {
193+ return
194+ }
195+
196+ #if DEBUG
197+ self . forwardDataToHandler ( data)
198+ #endif
199+ }
200+
201+ stderrPipe. fileHandleForReading. readabilityHandler = { [ unowned self] handle in
202+ let data = handle. availableData
203+
204+ guard !data. isEmpty else {
205+ return
206+ }
207+
208+ #if DEBUG
209+ self . forwardErrorDataToHandler ( data)
210+ #endif
211+ }
212+ }
213+
214+ private func forwardDataToHandler( _ data: Data ) {
215+ queue. async { [ weak self] in
216+ guard let self = self else { return }
217+
218+ if self . closed {
219+ return
220+ }
221+
222+ if let string = String ( bytes: data, encoding: . utf8) {
223+ Logger . codeium. info ( " stdout: \( string) " )
224+ }
225+ }
226+ }
227+
228+ private func forwardErrorDataToHandler( _ data: Data ) {
229+ queue. async {
230+ if let string = String ( bytes: data, encoding: . utf8) {
231+ Logger . codeium. error ( " stderr: \( string) " )
232+ }
233+ }
234+ }
235+ }
236+
0 commit comments