Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/1304.enhancement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The `encode_proto` function was enhanced to automatically convert integer, float, and boolean values when passed to string proto fields.
50 changes: 49 additions & 1 deletion src/protobuf/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ fn convert_value_raw(
.map_err(|e| format!("Error setting 'nanos' field: {}", e))?;
Ok(prost_reflect::Value::Message(message))
}
(Value::Boolean(b), Kind::String) => Ok(prost_reflect::Value::String(b.to_string())),
(Value::Integer(i), Kind::String) => Ok(prost_reflect::Value::String(i.to_string())),
(Value::Float(f), Kind::String) => Ok(prost_reflect::Value::String(f.to_string())),
(Value::Timestamp(t), Kind::String) => Ok(prost_reflect::Value::String(t.to_string())),
_ => Err(format!(
"Cannot encode `{kind_str}` into protobuf `{kind:?}`",
)),
Expand Down Expand Up @@ -168,7 +172,12 @@ pub fn encode_message(
match map.get(field.name()) {
None | Some(Value::Null) => message.clear_field(&field),
Some(value) => message
.try_set_field(&field, convert_value(&field, value.clone())?)
.try_set_field(
&field,
convert_value(&field, value.clone()).map_err(|e| {
format!("Error converting {} field: {}", field.name(), e)
})?,
)
.map_err(|e| format!("Error setting {} field: {}", field.name(), e))?,
}
}
Expand Down Expand Up @@ -448,6 +457,45 @@ mod tests {
);
}

#[test]
fn test_encode_value_as_string() {
let mut message = encode_message(
&test_message_descriptor("Bytes"),
Value::Object(BTreeMap::from([("text".into(), Value::Boolean(true))])),
)
.unwrap();
assert_eq!(Some("true"), mfield!(message, "text").as_str());
message = encode_message(
&test_message_descriptor("Bytes"),
Value::Object(BTreeMap::from([("text".into(), Value::Integer(123))])),
)
.unwrap();
assert_eq!(Some("123"), mfield!(message, "text").as_str());
message = encode_message(
&test_message_descriptor("Bytes"),
Value::Object(BTreeMap::from([(
"text".into(),
Value::Float(NotNan::new(45.67).unwrap()),
)])),
)
.unwrap();
assert_eq!(Some("45.67"), mfield!(message, "text").as_str());
message = encode_message(
&test_message_descriptor("Bytes"),
Value::Object(BTreeMap::from([(
"text".into(),
Value::Timestamp(
DateTime::from_timestamp(8675, 309).expect("could not compute timestamp"),
),
)])),
)
.unwrap();
assert_eq!(
Some("1970-01-01 02:24:35.000000309 UTC"),
mfield!(message, "text").as_str()
);
}

fn read_pb_file(protobuf_bin_message_path: &str) -> String {
fs::read_to_string(test_data_dir().join(protobuf_bin_message_path)).unwrap()
}
Expand Down
4 changes: 4 additions & 0 deletions tests/data/protobuf/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
generate-desc:
protoc --proto_path=. --include_imports --descriptor_set_out=test.desc test.proto
protoc --proto_path=. --include_imports --descriptor_set_out=test_protobuf.desc test_protobuf.proto
protoc --proto_path=. --include_imports --descriptor_set_out=test_protobuf3.desc test_protobuf3.proto
61 changes: 61 additions & 0 deletions tests/data/protobuf/test.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
syntax = "proto3";

import "google/protobuf/timestamp.proto";

package test;

message Integers {
int32 i32 = 1;
int64 i64 = 2;
uint32 u32 = 3;
uint64 u64 = 4;
}

message Floats {
double d = 1;
float f = 2;
}

message Bytes {
string text = 1;
bytes binary = 2;
}

message Map {
message Person {
string nickname = 1;
uint32 age = 2;
}

map<string, int32> names = 1;
map<string, Person> people = 2;

}

message Enum {
enum Fruit {
APPLE = 0;
OLIVE = 1;
TOMATO = 2;
}
Fruit breakfast = 1;
Fruit lunch = 2;
Fruit dinner = 3;
}

message Timestamp {
google.protobuf.Timestamp morning = 1;
}

message RepeatedPrimitive {
repeated int64 numbers = 1;
}

message RepeatedMessage {
repeated EmbeddedMessage messages = 1;

message EmbeddedMessage {
optional string text = 1;
optional uint32 index = 2;
}
}
Binary file modified tests/data/protobuf/test_protobuf.desc
Binary file not shown.
Binary file modified tests/data/protobuf/test_protobuf3.desc
Binary file not shown.
Loading