如何将数据传递到 tonic 中的 protobuf `oneof` ?

yuk*_*say 4 protocol-buffers rust grpc prost

如何将数据传递到toniconeof中的protobuf ?

我在文档中找不到任何说明或示例。

sun*_*ide 6

Tonic 应该enum为每个变体生成一个相应的类型oneof。你必须匹配这一点。


我假设这个答案是tonic = "0.4.3"和或更高。prost = "0.7.0"让我们使用以下.proto定义作为示例:

syntax = "proto3";

package stack_overflow;

service StackOverflow {
  rpc Question (HelpRequest) returns (HelpResponse);
}

message HelpRequest {
  oneof foo {
    FroozleType froozle = 1;
    FrobnikType frobnik = 2;
  }
}

message FroozleType {
  int32 value = 1;
}
message FrobnikType {}

message HelpResponse {
  oneof bar {
    QuxType qux = 1;
    BazType baz = 2;
  }
}

message QuxType {
  int32 answer = 1;
}
message BazType {
  string comment = 1;
}
Run Code Online (Sandbox Code Playgroud)

构建后,会生成以下类型和特征。对于服务:

  • stack_overflow_server::StackOverflow:服务器特征

对于请求:

  • HelpRequest:请求消息的结构体
  • help_request::Foooneof foo:请求中具有FroozleFrobnik变体的枚举
  • FroozleTypeFroozleType:消息的结构
  • FrobnikTypeFrobnikType:消息的结构

对于答复:

  • HelpResponse:响应消息的结构体
  • help_response::Baroneof bar:响应中具有QuxBaz变体的枚举
  • QuxTypeQuxType:消息的结构
  • BazTypeBazType:消息的结构

例如,HelpRequest结构体和help_request::Foo枚举的定义如下:

#[derive(Clone, PartialEq, ::prost::Message)]
pub struct HelpRequest {
    #[prost(oneof = "help_request::Foo", tags = "1, 2")]
    pub foo: ::core::option::Option<help_request::Foo>,
}

/// Nested message and enum types in `HelpRequest`.
pub mod help_request {
    #[derive(Clone, PartialEq, ::prost::Oneof)]
    pub enum Foo {
        #[prost(message, tag = "1")]
        Froozle(super::FroozleType),
        #[prost(message, tag = "2")]
        Frobnik(super::FrobnikType),
    }
}
Run Code Online (Sandbox Code Playgroud)

将所有内容放在一起,上述服务的示例实现可能如下所示:

use tonic::{Request, Response, Status};

mod grpc {
    tonic::include_proto!("stack_overflow");
}

#[derive(Debug)]
pub struct StackOverflowService {}

#[tonic::async_trait]
impl grpc::stack_overflow_server::StackOverflow for StackOverflowService {
    async fn question(
        &self,
        request: Request<grpc::HelpRequest>,
    ) -> Result<Response<grpc::HelpResponse>, Status> {
        let request = request.into_inner();

        let bar = match request.foo {
            Some(grpc::help_request::Foo::Froozle(froozle)) => {
                Some(grpc::help_response::Bar::Qux(grpc::QuxType {
                    answer: froozle.value + 42,
                }))
            }
            Some(grpc::help_request::Foo::Frobnik(_)) => {
                Some(grpc::help_response::Bar::Baz(grpc::BazType {
                    comment: "forty-two".into(),
                }))
            }
            None => None,
        };

        let reply = grpc::HelpResponse { bar };
        return Ok(Response::new(reply));
    }
}
Run Code Online (Sandbox Code Playgroud)