我正在尝试序列化数据,该数据由以下 protobuf 文件指定:
syntax = "proto3";
package efficient_servers.protobuf;
message Request {
oneof msg {
Walk walk = 1;
OneToOne oneToOne = 2;
OneToAll oneToAll = 3;
Reset reset = 4;
}
}
message Walk {
repeated Location locations = 1; // repeated n times, determines edge directions
repeated uint32 lengths = 2; // [mm], repeated n-1 times
}
message OneToOne {
Location origin = 1;
Location destination = 2;
}
message OneToAll {
Location origin = 1;
}
message Reset {}
message Location {
int32 x = 1; // [mm]
int32 y = 2; // [mm]
}
message Response {
enum Status {OK = 0; ERROR = 1;};
Status status = 1; // Always present
string errMsg = 2;
uint64 shortest_path_length = 3; // [mm]
uint64 total_length = 4; // [mm]
}
我需要创建一个
Response
,它只有用 OK
变体填充的状态字段,encoded_len()
函数返回 0。对我来说,这似乎是消息的默认值被忽略编码器,这是可以理解的,它希望最小化消息大小。但是,如果我只想发送一条带有单个默认字段的消息怎么办?在这种情况下,消息大小为零,并且不会对消息进行编码。
有办法解决这个废话吗?请注意,我无法编辑 .proto 规范文件。
我尝试仅使用状态枚举的
ERROR
变体,并返回有效的非零 encoded_len()
,但我还需要序列化为 OK
变体。
我正在使用以下代码:
pub fn generate_response(data: Result<RequestResponse, String>) -> BytesMut {
let mut response = Response::default();
match data {
Ok(request_response) => {
match request_response.request {
Msg::Reset(_) => {
response.set_status(Status::Ok);
},
Msg::OneToAll(_) => {
response.set_status(Status::Ok);
response.shortest_path_length = request_response.length;
}
Msg::OneToOne(_) => {
response.set_status(Status::Ok);
response.total_length = request_response.length;
}
Msg::Walk(_) => {
response.set_status(Status::Ok);
},
}
}
Err(msg) => {
response.set_status(Status::Error);
response.err_msg = msg.parse().unwrap();
}
}
let encoded_len = response.encoded_len();
let mut buf = BytesMut::with_capacity(encoded_len);
buf.resize(encoded_len, 0);
response.encode(&mut buf).unwrap();
return buf;
}
总而言之,当 ResponseRequest.request 为 Msg::Reset 或 Msg:Walk 时,encoded_len() 函数返回 0,这意味着我没有序列化数据,因此没有要发送的数据。
但是如果我只想发送一条带有单个默认字段的消息怎么办?在这种情况下,消息大小为零,并且不会对消息进行编码。
因此,您发送长度为 0 的响应,接收方将其解码为
Response
,最终得到一个仅包含默认值的 Response
消息实例。
这不应该导致任何问题,假设您使用的任何传输都能够说“响应的长度为X”,因此能够处理空响应。
请注意,如果您在其他消息类型中有
Response
字段,“此字段填充有默认消息”和“此字段未填充”之间仍然存在差异 - 您最终会得到标签对于该字段,然后是 0 字节长度前缀的消息。