aboutsummaryrefslogtreecommitdiff
path: root/src/gen/file_descriptor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/gen/file_descriptor.rs')
-rw-r--r--src/gen/file_descriptor.rs208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/gen/file_descriptor.rs b/src/gen/file_descriptor.rs
new file mode 100644
index 0000000..2c8249c
--- /dev/null
+++ b/src/gen/file_descriptor.rs
@@ -0,0 +1,208 @@
+use std::fmt::Write as _;
+
+use protobuf::reflect::FileDescriptor;
+use protobuf::Message;
+
+use crate::gen::code_writer::CodeWriter;
+use crate::gen::inside::protobuf_crate_path;
+use crate::gen::paths::proto_path_to_fn_file_descriptor;
+use crate::gen::rust::snippets::expr_vec_with_capacity_const;
+use crate::gen::scope::FileScope;
+use crate::gen::scope::Scope;
+use crate::gen::scope::WithScope;
+use crate::Customize;
+
+fn escape_byte(s: &mut String, b: u8) {
+ if b == b'\n' {
+ write!(s, "\\n").unwrap();
+ } else if b == b'\r' {
+ write!(s, "\\r").unwrap();
+ } else if b == b'\t' {
+ write!(s, "\\t").unwrap();
+ } else if b == b'\\' || b == b'"' {
+ write!(s, "\\{}", b as char).unwrap();
+ } else if b == b'\0' {
+ write!(s, "\\0").unwrap();
+ // ASCII printable except space
+ } else if b > 0x20 && b < 0x7f {
+ write!(s, "{}", b as char).unwrap();
+ } else {
+ write!(s, "\\x{:02x}", b).unwrap();
+ }
+}
+
+fn write_generate_file_descriptor(
+ file_descriptor: &FileDescriptor,
+ customize: &Customize,
+ w: &mut CodeWriter,
+) {
+ let deps = &file_descriptor.proto().dependency;
+ w.write_line(&format!(
+ "let mut deps = {vec_with_capacity};",
+ vec_with_capacity = expr_vec_with_capacity_const(deps.len())
+ ));
+ for f in deps {
+ w.write_line(&format!(
+ "deps.push({}().clone());",
+ proto_path_to_fn_file_descriptor(f, customize)
+ ));
+ }
+
+ let scope = FileScope { file_descriptor };
+
+ let messages = scope.find_messages_except_map();
+ w.write_line(&format!(
+ "let mut messages = {vec_with_capacity};",
+ vec_with_capacity = expr_vec_with_capacity_const(messages.len())
+ ));
+ for m in &messages {
+ w.write_line(&format!(
+ "messages.push({}::generated_message_descriptor_data());",
+ m.rust_name_to_file(),
+ ));
+ }
+
+ let enums = scope.find_enums();
+ w.write_line(&format!(
+ "let mut enums = {};",
+ expr_vec_with_capacity_const(enums.len())
+ ));
+ for e in &enums {
+ w.write_line(&format!(
+ "enums.push({}::generated_enum_descriptor_data());",
+ e.rust_name_to_file(),
+ ));
+ }
+
+ w.write_line(&format!(
+ "{}::reflect::GeneratedFileDescriptor::new_generated(",
+ protobuf_crate_path(&customize),
+ ));
+ w.indented(|w| {
+ w.write_line(&format!("file_descriptor_proto(),"));
+ w.write_line(&format!("deps,"));
+ w.write_line(&format!("messages,"));
+ w.write_line(&format!("enums,"));
+ });
+ w.write_line(")");
+}
+
+fn write_file_descriptor(
+ file_descriptor: &FileDescriptor,
+ customize: &Customize,
+ w: &mut CodeWriter,
+) {
+ w.write_line("/// `FileDescriptor` object which allows dynamic access to files");
+ w.pub_fn(
+ &format!(
+ "file_descriptor() -> &'static {protobuf_crate}::reflect::FileDescriptor",
+ protobuf_crate = protobuf_crate_path(customize)
+ ),
+ |w| {
+ w.lazy_static(
+ "generated_file_descriptor_lazy",
+ &format!(
+ "{protobuf_crate}::reflect::GeneratedFileDescriptor",
+ protobuf_crate = protobuf_crate_path(customize)
+ ),
+ &format!("{}", protobuf_crate_path(customize)),
+ );
+ w.lazy_static_decl_get(
+ "file_descriptor",
+ &format!(
+ "{protobuf_crate}::reflect::FileDescriptor",
+ protobuf_crate = protobuf_crate_path(customize)
+ ),
+ &format!("{}", protobuf_crate_path(customize)),
+ |w| {
+ w.block(
+ "let generated_file_descriptor = generated_file_descriptor_lazy.get(|| {",
+ "});",
+ |w| write_generate_file_descriptor(file_descriptor, customize, w),
+ );
+ w.write_line(&format!(
+ "{protobuf_crate}::reflect::FileDescriptor::new_generated_2(generated_file_descriptor)",
+ protobuf_crate=protobuf_crate_path(&customize),
+ ));
+ }
+ );
+ },
+ );
+}
+
+pub(crate) fn write_file_descriptor_data(
+ file: &FileDescriptor,
+ customize: &Customize,
+ w: &mut CodeWriter,
+) {
+ let fdp_bytes = file.proto().write_to_bytes().unwrap();
+ w.write_line("static file_descriptor_proto_data: &'static [u8] = b\"\\");
+ w.indented(|w| {
+ const MAX_LINE_LEN: usize = 72;
+
+ let mut s = String::new();
+ for &b in &fdp_bytes {
+ let prev_len = s.len();
+ escape_byte(&mut s, b);
+ let truncate = s.len() > MAX_LINE_LEN;
+ if truncate {
+ s.truncate(prev_len);
+ }
+ if truncate || s.len() == MAX_LINE_LEN {
+ write!(s, "\\").unwrap();
+ w.write_line(&s);
+ s.clear();
+ }
+ if truncate {
+ escape_byte(&mut s, b);
+ }
+ }
+ if !s.is_empty() {
+ write!(s, "\\").unwrap();
+ w.write_line(&s);
+ s.clear();
+ }
+ });
+ w.write_line("\";");
+ w.write_line("");
+ write_file_descriptor_proto(&customize, w);
+ w.write_line("");
+ write_file_descriptor(file, &customize, w);
+}
+
+fn write_file_descriptor_proto(customize: &Customize, w: &mut CodeWriter) {
+ w.write_line("/// `FileDescriptorProto` object which was a source for this generated file");
+ w.def_fn(
+ &format!(
+ "file_descriptor_proto() -> &'static {protobuf_crate}::descriptor::FileDescriptorProto",
+ protobuf_crate=protobuf_crate_path(customize)
+ ),
+ |w| {
+ w.lazy_static_decl_get(
+ "file_descriptor_proto_lazy",
+ &format!(
+ "{protobuf_crate}::descriptor::FileDescriptorProto",
+ protobuf_crate=protobuf_crate_path(customize)
+ ),
+ &format!("{}", protobuf_crate_path(customize)),
+ |w| {
+ w.write_line(&format!(
+ "{protobuf_crate}::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()",
+ protobuf_crate=protobuf_crate_path(customize)
+ ));
+ },
+ );
+ },
+ );
+}
+
+/// Code to generate call `module::file_descriptor()`.
+pub(crate) fn file_descriptor_call_expr(scope: &Scope) -> String {
+ format!(
+ "{}()",
+ scope
+ .rust_path_to_file()
+ .to_reverse()
+ .append_ident("file_descriptor".into())
+ )
+}