Skip to content

Commit e5988a5

Browse files
authored
feat(stdlib): Add proto_encode and parse_proto to encode and parse protocol buffers (#739)
* Add proto_encode and parse_proto to encode and parse protocol buffers parse_proto accepts a bytes value, a proto descriptor file path and a message type and returns the VRL value as parsed from the proto. `parse_proto!(base64_decode("data"), "person.desc", "proto.Person")` `=> {"id": 42, "name": "John Doe"}` For `encode_proto`, it does the reverse: `encode_proto!({"id": 42, "name": "John Doe"}, "person.desc", "proto.Person")` `=> bytes data` Note that the path to descriptor file and message type are required to be literals. We do this so that during compilation we load the message descriptor and reuse it for encoding or parsing. Most of the code was copied over from the protobuf codec support from vector. However, there's one notable difference. In `parse_proto`, we don't set fields that are not set. This ensures that encode_proto and parse_proto remain symmetric (decoding the result of parsing will return the original result). * Address comments and move common protobuf logic into src/protobuf * Fix clippy issues * Add changelog entry * Update LICENSE-3rdparty.csv * Fix examples
1 parent f25ea7c commit e5988a5

20 files changed

+1060
-0
lines changed

Cargo.lock

+45
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+6
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ stdlib = [
8282
"dep:ofb",
8383
"dep:once_cell",
8484
"dep:percent-encoding",
85+
"dep:prost",
86+
"dep:prost-reflect",
8587
"dep:psl",
8688
"dep:quoted_printable",
8789
"dep:rand",
@@ -186,6 +188,10 @@ cbc = { version = "0.1", optional = true, features = ["alloc"] }
186188
cfb-mode = { version = "0.8", optional = true }
187189
ofb = { version = "0.6", optional = true }
188190

191+
# Protobuf support.
192+
prost = { version = "0.12", default-features = false, optional = true, features = ["std"]}
193+
prost-reflect = { version = "0.13", default-features = false, optional = true}
194+
189195
# Dependencies used for non-WASM
190196
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
191197
dns-lookup = { version = "2", optional = true }

LICENSE-3rdparty.csv

+3
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ prettytable-rs,https://github.com/phsym/prettytable-rs,BSD-3-Clause,Pierre-Henri
133133
proc-macro-crate,https://github.com/bkchr/proc-macro-crate,MIT OR Apache-2.0,Bastian Köcher <git@kchr.de>
134134
proc-macro-error,https://gitlab.com/CreepySkeleton/proc-macro-error,MIT OR Apache-2.0,CreepySkeleton <creepy-skeleton@yandex.ru>
135135
proc-macro2,https://github.com/dtolnay/proc-macro2,MIT OR Apache-2.0,"David Tolnay <dtolnay@gmail.com>, Alex Crichton <alex@alexcrichton.com>"
136+
prost,https://github.com/tokio-rs/prost,Apache-2.0,"Dan Burkert <dan@danburkert.com>, Lucio Franco <luciofranco14@gmail.com, Tokio Contributors <team@tokio.rs>"
137+
prost-derive,https://github.com/tokio-rs/prost,Apache-2.0,"Dan Burkert <dan@danburkert.com>, Lucio Franco <luciofranco14@gmail.com>, Tokio Contributors <team@tokio.rs>"
138+
prost-reflect,https://github.com/andrewhickman/prost-reflect,MIT OR Apache-2.0,Andrew Hickman <andrew.hickman1@sky.com>
136139
psl,https://github.com/addr-rs/psl,MIT OR Apache-2.0,rushmorem <rushmore@webenchanter.com>
137140
psl-types,https://github.com/addr-rs/psl-types,MIT OR Apache-2.0,rushmorem <rushmore@webenchanter.com>
138141
ptr_meta,https://github.com/djkoloski/ptr_meta,MIT,David Koloski <djkoloski@gmail.com>

changelog.d/739.feature.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Added `encode_proto` and `parse_proto` functions, which can be used to encode and decode protobufs.
2+
3+
`parse_proto` accepts a bytes value, a proto descriptor file path and a message type and returns the VRL value as parsed from the proto. `encode_proto` does the reverse and converts a VRL value into a protobuf bytes value.
1.16 KB
Binary file not shown.

src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ pub mod core;
3030
#[cfg(feature = "stdlib")]
3131
pub mod stdlib;
3232

33+
#[cfg(feature = "stdlib")]
34+
pub mod protobuf;
35+
3336
#[cfg(feature = "cli")]
3437
pub mod cli;
3538

src/protobuf/descriptor.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use prost_reflect::{DescriptorPool, MessageDescriptor};
2+
use std::path::Path;
3+
4+
pub fn get_message_descriptor(
5+
descriptor_set_path: &Path,
6+
message_type: &str,
7+
) -> std::result::Result<MessageDescriptor, String> {
8+
let b = std::fs::read(descriptor_set_path).map_err(|e| {
9+
format!("Failed to open protobuf desc file '{descriptor_set_path:?}': {e}",)
10+
})?;
11+
let pool = DescriptorPool::decode(b.as_slice()).map_err(|e| {
12+
format!("Failed to parse protobuf desc file '{descriptor_set_path:?}': {e}")
13+
})?;
14+
pool.get_message_by_name(message_type).ok_or_else(|| {
15+
format!("The message type '{message_type}' could not be found in '{descriptor_set_path:?}'")
16+
})
17+
}

0 commit comments

Comments
 (0)