1use clap::{Parser, Subcommand, ValueEnum};
2use std::path::PathBuf;
3
4#[derive(Parser)]
5#[command(name = "layout-audit")]
6#[command(
7 author,
8 version,
9 about = "Analyze binary memory layouts to detect padding inefficiencies"
10)]
11#[command(
12 long_about = "layout-audit parses DWARF debugging information to visualize the physical \
13layout of data structures, detect padding holes, and analyze cache line efficiency.\n\n\
14Example:\n layout-audit inspect ./target/debug/myapp --filter MyStruct"
15)]
16pub struct Cli {
17 #[command(subcommand)]
18 pub command: Commands,
19}
20
21#[derive(Subcommand)]
22pub enum Commands {
23 Inspect {
25 #[arg(value_name = "BINARY")]
27 binary: PathBuf,
28
29 #[arg(short, long)]
31 filter: Option<String>,
32
33 #[arg(short, long, value_enum, default_value = "table")]
35 output: OutputFormat,
36
37 #[arg(short, long, value_enum, default_value = "name")]
39 sort_by: SortField,
40
41 #[arg(short = 'n', long)]
43 top: Option<usize>,
44
45 #[arg(long)]
47 min_padding: Option<u64>,
48
49 #[arg(long)]
51 no_color: bool,
52
53 #[arg(long, default_value = "64", value_parser = clap::value_parser!(u32).range(1..))]
55 cache_line: u32,
56
57 #[arg(long)]
59 pretty: bool,
60
61 #[arg(long)]
63 warn_false_sharing: bool,
64
65 #[arg(long)]
67 include_go_runtime: bool,
68 },
69
70 Diff {
72 #[arg(value_name = "OLD")]
74 old: PathBuf,
75
76 #[arg(value_name = "NEW")]
78 new: PathBuf,
79
80 #[arg(short, long)]
82 filter: Option<String>,
83
84 #[arg(short, long, value_enum, default_value = "table")]
86 output: OutputFormat,
87
88 #[arg(long, default_value = "64", value_parser = clap::value_parser!(u32).range(1..))]
90 cache_line: u32,
91
92 #[arg(long)]
94 fail_on_regression: bool,
95
96 #[arg(long)]
98 include_go_runtime: bool,
99 },
100
101 Check {
103 #[arg(value_name = "BINARY")]
105 binary: PathBuf,
106
107 #[arg(short, long, default_value = ".layout-audit.yaml")]
109 config: PathBuf,
110
111 #[arg(long, default_value = "64", value_parser = clap::value_parser!(u32).range(1..))]
113 cache_line: u32,
114
115 #[arg(long)]
117 include_go_runtime: bool,
118 },
119
120 Suggest {
122 #[arg(value_name = "BINARY")]
124 binary: PathBuf,
125
126 #[arg(short, long)]
128 filter: Option<String>,
129
130 #[arg(short, long, value_enum, default_value = "table")]
132 output: OutputFormat,
133
134 #[arg(long)]
136 min_savings: Option<u64>,
137
138 #[arg(long, default_value = "64", value_parser = clap::value_parser!(u32).range(1..))]
140 cache_line: u32,
141
142 #[arg(long)]
144 pretty: bool,
145
146 #[arg(long, default_value = "8", value_parser = clap::value_parser!(u64).range(1..))]
148 max_align: u64,
149
150 #[arg(long)]
152 sort_by_savings: bool,
153
154 #[arg(long)]
156 no_color: bool,
157
158 #[arg(long)]
160 include_go_runtime: bool,
161 },
162}
163
164#[derive(Copy, Clone, PartialEq, Eq, ValueEnum)]
165pub enum OutputFormat {
166 Table,
167 Json,
168}
169
170#[derive(Copy, Clone, PartialEq, Eq, ValueEnum)]
171pub enum SortField {
172 Name,
174 Size,
176 Padding,
178 PaddingPct,
180}