Skip to main content

oxiproto_codegen/
lib.rs

1#![forbid(unsafe_code)]
2
3//! `oxiproto-codegen` — Generate plain Rust source code from a `FileDescriptorSet`.
4//!
5//! This crate walks a `prost_types::FileDescriptorSet` and emits plain Rust
6//! structs and enums — no prost derive, no gRPC stubs, no validators.
7//!
8//! ## Quick start
9//!
10//! ```no_run
11//! use prost_types::FileDescriptorSet;
12//!
13//! let fds: FileDescriptorSet = /* parse your .proto */ Default::default();
14//! let rust_src = oxiproto_codegen::generate(&fds).expect("codegen failed");
15//! println!("{rust_src}");
16//! ```
17
18pub(crate) mod builder_impl;
19mod emit;
20mod format;
21mod json_impl;
22mod message_impl;
23mod options;
24pub(crate) mod text_impl;
25pub(crate) mod type_registry;
26pub mod wkt_map;
27
28pub use options::{CodegenError, CodegenOptions};
29
30pub use emit::{emit_file_descriptor_set, emit_file_descriptor_set_with_options, ModuleTree};
31
32/// Generate Rust source code from a `FileDescriptorSet`.
33///
34/// Returns a `String` of Rust source containing `struct` and `enum` definitions
35/// for every message and enum found in the descriptor set.  Fields are mapped
36/// to plain Rust types (no `prost` derive macros).
37pub fn generate(fds: &prost_types::FileDescriptorSet) -> Result<String, CodegenError> {
38    emit::emit_file_descriptor_set(fds)
39}
40
41/// Generate Rust source code with custom codegen options.
42///
43/// This allows enabling additional features like doc comment generation,
44/// `Default` impls, deprecation attributes, and BTreeMap for map fields.
45pub fn generate_with_options(
46    fds: &prost_types::FileDescriptorSet,
47    options: &CodegenOptions,
48) -> Result<String, CodegenError> {
49    let code = emit::emit_file_descriptor_set_with_options(fds, options)?;
50    #[cfg(feature = "format")]
51    let code = if options.format_output {
52        crate::format::format_source(&code)?
53    } else {
54        code
55    };
56    Ok(code)
57}
58
59/// Generate a structured module tree from a `FileDescriptorSet`.
60///
61/// Unlike [`generate_with_options`] which returns a flat `String`,
62/// this returns a [`ModuleTree`] that preserves the package hierarchy,
63/// enabling per-package or per-file output.
64///
65/// # Errors
66///
67/// Returns a [`CodegenError`] if the descriptor set is invalid.
68pub fn generate_module(
69    fds: &prost_types::FileDescriptorSet,
70    options: &CodegenOptions,
71) -> Result<ModuleTree, CodegenError> {
72    emit::generate_module_tree(fds, options)
73}
74
75/// Write generated code to a file path.
76///
77/// Equivalent to calling [`generate`] and then writing the resulting string to
78/// `path`.
79pub fn generate_to_file(
80    fds: &prost_types::FileDescriptorSet,
81    path: &std::path::Path,
82) -> Result<(), CodegenError> {
83    let code = generate(fds)?;
84    std::fs::write(path, code).map_err(CodegenError::Io)
85}
86
87/// Write generated code to a file path with custom options.
88pub fn generate_to_file_with_options(
89    fds: &prost_types::FileDescriptorSet,
90    path: &std::path::Path,
91    options: &CodegenOptions,
92) -> Result<(), CodegenError> {
93    let code = generate_with_options(fds, options)?;
94    std::fs::write(path, code).map_err(CodegenError::Io)
95}