use std::path::PathBuf;
use clap::{CommandFactory, Parser, Subcommand};
use clap_complete::engine::ArgValueCompleter;
use complete::{
complete_any_path, complete_descriptor_path, complete_dir_path, complete_input_paths,
complete_type_names,
};
pub mod complete;
pub mod inputs;
pub mod lazy_pool;
pub mod run;
pub static EMBEDDED_DESCRIPTOR: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/descriptor.pb"));
#[cfg(feature = "wkt-db")]
pub static WKT_GRAPH: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/wkt.rkyv"));
#[cfg(feature = "wkt-db")]
pub static WKT_INDEX: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/wkt_index.rkyv"));
#[derive(Debug, Parser)]
#[command(
name = "prototext",
version,
about,
long_about = None,
after_help = "\
Examples:
# Decode to stdout (schemaless)
prototext decode foo.pb
# Decode with schema; annotations included by default
prototext --descriptor-set my.desc decode --type com.example.Foo foo.pb
# Suppress annotations (protoc-compatible output)
prototext --descriptor-set my.desc decode --type com.example.Foo \\
--no-annotations foo.pb
# Identify the schema of an unknown binary
prototext --descriptor-set my.desc list-schemas foo.pb
# Encode prototext back to binary
prototext encode foo.txtpb -o foo.pb",
)]
pub struct Cli {
#[arg(
long = "descriptor-set",
alias = "descriptor",
value_name = "DESCRIPTOR_SET_FILE",
env = "PROTOTEXT_DESCRIPTOR_SET",
add = ArgValueCompleter::new(complete_descriptor_path),
)]
pub descriptor: Option<PathBuf>,
#[arg(
short = 'o',
long = "output",
value_name = "PATH",
conflicts_with = "output_root",
add = ArgValueCompleter::new(complete_any_path),
)]
pub output: Option<PathBuf>,
#[arg(
short = 'O',
long = "output-root",
value_name = "DIR",
conflicts_with_all = ["output"],
add = ArgValueCompleter::new(complete_dir_path),
)]
pub output_root: Option<PathBuf>,
#[arg(
short = 'I',
long = "input-root",
value_name = "DIR",
add = ArgValueCompleter::new(complete_dir_path),
)]
pub input_root: Option<PathBuf>,
#[arg(short = 'q', long = "quiet")]
pub quiet: bool,
#[command(subcommand)]
pub command: Command,
}
#[derive(Debug, Subcommand)]
pub enum Command {
Decode {
#[arg(
short = 't',
long = "type",
value_name = "NAME",
conflicts_with = "raw",
add = ArgValueCompleter::new(complete_type_names),
)]
r#type: Option<String>,
#[arg(long, conflicts_with = "type")]
raw: bool,
#[arg(short = 'i', long = "in-place")]
in_place: bool,
#[arg(long = "assume-binary")]
assume_binary: bool,
#[arg(long = "no-annotations")]
no_annotations: bool,
#[arg(long = "detailed-score", help_heading = "Advanced options")]
detailed_score: bool,
#[arg(
long = "relax-ranges",
alias = "no-strict-ranges",
help_heading = "Advanced options"
)]
relax_ranges: bool,
#[arg(long = "no-expand-any", help_heading = "Advanced options")]
no_expand_any: bool,
#[arg(long = "strict", help_heading = "Advanced options")]
strict: bool,
#[arg(
value_name = "PATH",
add = ArgValueCompleter::new(complete_input_paths),
)]
paths: Vec<String>,
},
Encode {
#[arg(short = 'i', long = "in-place")]
in_place: bool,
#[arg(
value_name = "PATH",
add = ArgValueCompleter::new(complete_input_paths),
)]
paths: Vec<String>,
},
#[command(name = "list-schemas")]
ListSchemas {
#[arg(long = "top", value_name = "N")]
top: Option<usize>,
#[arg(long = "assume-binary")]
assume_binary: bool,
#[arg(long = "detailed-score", help_heading = "Advanced options")]
detailed_score: bool,
#[arg(
long = "relax-ranges",
alias = "no-strict-ranges",
help_heading = "Advanced options"
)]
relax_ranges: bool,
#[arg(long = "no-expand-any", help_heading = "Advanced options")]
no_expand_any: bool,
#[arg(
value_name = "PATH",
add = ArgValueCompleter::new(complete_input_paths),
)]
paths: Vec<String>,
},
Score {
#[arg(
short = 't',
long = "type",
value_name = "NAME",
required = true,
add = ArgValueCompleter::new(complete_type_names),
)]
r#type: String,
#[arg(long = "assume-binary")]
assume_binary: bool,
#[arg(
long = "relax-ranges",
alias = "no-strict-ranges",
help_heading = "Advanced options"
)]
relax_ranges: bool,
#[arg(
value_name = "PATH",
add = ArgValueCompleter::new(complete_input_paths),
)]
paths: Vec<String>,
},
}
pub fn command() -> clap::Command {
Cli::command()
}