File: InProcPluginServer.swift

package info (click to toggle)
swiftlang 6.2.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,856,264 kB
  • sloc: cpp: 9,995,718; ansic: 2,234,019; asm: 1,092,167; python: 313,940; objc: 82,726; f90: 80,126; lisp: 38,373; pascal: 25,580; sh: 20,378; ml: 5,058; perl: 4,751; makefile: 4,725; awk: 3,535; javascript: 3,018; xml: 918; fortran: 664; cs: 573; ruby: 396
file content (90 lines) | stat: -rw-r--r-- 2,824 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

@_spi(PluginMessage) import SwiftCompilerPluginMessageHandling
@_spi(PluginMessage) import SwiftLibraryPluginProvider

#if canImport(Darwin)
import Darwin
#elseif canImport(Glibc)
import Glibc
#elseif canImport(Bionic)
import Bionic
#elseif canImport(Musl)
import Musl
#elseif canImport(ucrt)
import ucrt
#else
#error("'malloc' not found")
#endif

/// Entry point.
///
/// Compiler 'dlopen' this 'SwiftInProcPluginServer' library, and 'dlsym' this
/// function. When the compiler wants to use dylib plugins, it calls this
/// function with the same message as `swift-plugin-server`.
///
/// The caller must `free` the returned buffer
@_cdecl("swift_inproc_plugins_handle_message")
@MainActor
public func handleMessage(
  _ inputData: UnsafePointer<UInt8>!,
  _ inputLength: Int,
  _ outputData: UnsafeMutablePointer<UnsafeMutablePointer<UInt8>?>!,
  _ outputLength: UnsafeMutablePointer<Int>!
) -> Bool {
  do {
    let input = UnsafeBufferPointer(start: inputData, count: inputLength)
    let output = try InProcPluginServer.shared.handleMessage(input)
    output.withUnsafeBufferPointer(fillOutput(_:))
    return false // Success.
  } catch {
    var message = "Internal Error: \(error)"
    message.withUTF8(fillOutput(_:))
    return true // Error.
  }

  func fillOutput(_ responseData: UnsafeBufferPointer<UInt8>) {
    // NOTE: Use 'malloc' instead of 'UnsafeMutablePointer.allocate()' so that
    // C/C++ clients can deallocate it without using Swift.
    let buffer = malloc(responseData.count)!
    buffer.initializeMemory(
      as: UInt8.self,
      from: responseData.baseAddress!,
      count: responseData.count
    )
    outputData.pointee = buffer.assumingMemoryBound(to: UInt8.self)
    outputLength.pointee = responseData.count
  }
}

/// Singleton "plugin server".
struct InProcPluginServer {
  private let handler: PluginProviderMessageHandler<LibraryPluginProvider>

  @MainActor
  private init() {
    self.handler = PluginProviderMessageHandler(
      provider: LibraryPluginProvider.shared
    )
  }

  func handleMessage(_ input: UnsafeBufferPointer<UInt8>) throws -> [UInt8] {
    let request = try JSON.decode(HostToPluginMessage.self, from: input)
    let response =  handler.handleMessage(request)
    return try JSON.encode(response)
  }

  @MainActor
  static let shared = Self()
}