Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate methods for Swift, not just structs #2502

Open
wbraynen opened this issue Jun 30, 2023 · 4 comments
Open

Generate methods for Swift, not just structs #2502

wbraynen opened this issue Jun 30, 2023 · 4 comments

Comments

@wbraynen
Copy link

wbraynen commented Jun 30, 2023

Consider the following "hello world" proto:
https://github.com/grpc/grpc/blob/master/examples/protos/helloworld.proto

Compare the following commands:

  1. java -jar wire-compiler-4.7.2-jar-with-dependencies.jar --proto_path=. --kotlin_out=. helloworld.proto
  2. java -jar wire-compiler-4.7.2-jar-with-dependencies.jar --proto_path=. --swift_out=. helloworld.proto

Running the Kotlin version (1 above) generates the following four files:

HelloReply.kt
HelloRequest.kt
GreeterClient.kt
GrpcGreeterClient.kt

Running the Swift version (2 above), however, generates only:

HelloReply.swift
HelloRequest.swift

How to generate the two missing files for Swift also? (For example, a Swift protocol and a class or struct that conforms to that protocol, which contains Swift methods?) Otherwise all we have is models (structs). If it's not currently possible to generate Swift methods, what is the use case for the Swift Wire version in its current form?

@oldergod
Copy link
Member

oldergod commented Jul 1, 2023

Generating services in swift is not currently supported. I don't believe there are any short term plans to generate something; do you have something in mind of what it would look like?

@wbraynen
Copy link
Author

wbraynen commented Jul 1, 2023

Generating services in swift is not currently supported. I don't believe there are any short term plans to generate something; do you have something in mind of what it would look like?

Given https://github.com/grpc/grpc/blob/master/examples/protos/helloworld.proto as sample input, without streaming, at a minimum, could just be:

class Greeter {
    func SayHello(request: HelloRequest) async -> HelloReply {
        // implementation
    }
}

Plus could add public as needed, along with a protocol the class conforms to. Or same thing with a protocol if we want to abstract away the implementation.

If it needs to throw an exception or two, the function signature would then be:

func SayHello(request: HelloRequest) async throws -> HelloReply

Plus, ideally, it would follow Swift namespacing conventions as mentioned in this proposal in the alternative repo: apple/swift-protobuf#750 (which I think was maybe met with resistance there).

@upanshu21
Copy link

@oldergod @lickel any updates around this?

@lickel
Copy link
Collaborator

lickel commented Jul 8, 2023

We briefly talked about it. There's no current timeline for when this might be tackled.
What we did talk about is we would not want to have a full on implementation as you described.

At a minimum we would want the actual networking to be protocol oriented such that you could use (for example) Alamofire, raw URLSessions, or a custom library.

@oldergod pointed out that the Kotlin generated code is built upon GrpcClient

As far as naming is concerned, we would almost certainly follow existing patterns within Wire.

public struct HelloRequest: ProtoMessage {
    public var name: String?
}

public struct HelloReply: ProtoMessage {
    public var message: String?
}

As for what the Greeter object would look like, I could see one of two solutions:

  1. A struct that is inited with a GRPC client:
public struct Greeter: GRPCService {
    public init(client: GRPCClient) { ... }

    func SayHello(request: HelloRequest) async throws -> HelloReply { ... }
}
  1. A protocol with a default implementation when it also conforms to a GRPC client:
protocol Greeter {
    func SayHello(request: HelloRequest) async throws -> HelloReply
}

extension Greeter where Self: GRPCClient {
    public func SayHello(request: HelloRequest) async throws -> HelloReply { ... }
}

2 has the benefit of letting you mock Greeter without mocking out the entire GRPC interface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants