mirror of https://github.com/encounter/objdiff.git
Let-else reformatting (#23)
* Use let-else in App::post_rendering * Use let-else in diff::reloc_eq * Use let-else in diff::diff_objs * Use let-else in views::data_diff::data_diff_ui * Use let-else in views::function_diff::function_diff_ui * Use let-else in views::function_diff::asm_row_ui * Use let-else in views::jobs::jobs_ui * Update rust-version in Cargo.toml
This commit is contained in:
parent
c7b6ec83d7
commit
20dcc50695
|
@ -2,7 +2,7 @@
|
|||
name = "objdiff"
|
||||
version = "0.2.3"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
authors = ["Luke Street <luke@street.dev>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/encounter/objdiff"
|
||||
|
|
113
src/app.rs
113
src/app.rs
|
@ -398,69 +398,64 @@ impl eframe::App for App {
|
|||
|
||||
fn post_rendering(&mut self, _window_size_px: [u32; 2], _frame: &eframe::Frame) {
|
||||
for job in &mut self.view_state.jobs {
|
||||
if let Some(handle) = &job.handle {
|
||||
if !handle.is_finished() {
|
||||
continue;
|
||||
}
|
||||
match job.handle.take().unwrap().join() {
|
||||
Ok(result) => {
|
||||
log::info!("Job {} finished", job.id);
|
||||
match result {
|
||||
JobResult::None => {
|
||||
if let Some(err) = &job.status.read().unwrap().error {
|
||||
log::error!("{:?}", err);
|
||||
}
|
||||
}
|
||||
JobResult::ObjDiff(state) => {
|
||||
self.view_state.build = Some(state);
|
||||
}
|
||||
JobResult::BinDiff(state) => {
|
||||
self.view_state.build = Some(Box::new(ObjDiffResult {
|
||||
first_status: BuildStatus {
|
||||
success: true,
|
||||
log: "".to_string(),
|
||||
},
|
||||
second_status: BuildStatus {
|
||||
success: true,
|
||||
log: "".to_string(),
|
||||
},
|
||||
first_obj: Some(state.first_obj),
|
||||
second_obj: Some(state.second_obj),
|
||||
time: OffsetDateTime::now_utc(),
|
||||
}));
|
||||
}
|
||||
JobResult::CheckUpdate(state) => {
|
||||
self.view_state.check_update = Some(state);
|
||||
}
|
||||
JobResult::Update(state) => {
|
||||
if let Ok(mut guard) = self.relaunch_path.lock() {
|
||||
*guard = Some(state.exe_path);
|
||||
}
|
||||
self.should_relaunch = true;
|
||||
let Some(handle) = &job.handle else {
|
||||
continue;
|
||||
};
|
||||
if !handle.is_finished() {
|
||||
continue;
|
||||
}
|
||||
match job.handle.take().unwrap().join() {
|
||||
Ok(result) => {
|
||||
log::info!("Job {} finished", job.id);
|
||||
match result {
|
||||
JobResult::None => {
|
||||
if let Some(err) = &job.status.read().unwrap().error {
|
||||
log::error!("{:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
let err = if let Some(msg) = err.downcast_ref::<&'static str>() {
|
||||
anyhow::Error::msg(*msg)
|
||||
} else if let Some(msg) = err.downcast_ref::<String>() {
|
||||
anyhow::Error::msg(msg.clone())
|
||||
} else {
|
||||
anyhow::Error::msg("Thread panicked")
|
||||
};
|
||||
let result = job.status.write();
|
||||
if let Ok(mut guard) = result {
|
||||
guard.error = Some(err);
|
||||
} else {
|
||||
drop(result);
|
||||
job.status = Arc::new(RwLock::new(JobStatus {
|
||||
title: "Error".to_string(),
|
||||
progress_percent: 0.0,
|
||||
progress_items: None,
|
||||
status: "".to_string(),
|
||||
error: Some(err),
|
||||
JobResult::ObjDiff(state) => {
|
||||
self.view_state.build = Some(state);
|
||||
}
|
||||
JobResult::BinDiff(state) => {
|
||||
self.view_state.build = Some(Box::new(ObjDiffResult {
|
||||
first_status: BuildStatus { success: true, log: "".to_string() },
|
||||
second_status: BuildStatus { success: true, log: "".to_string() },
|
||||
first_obj: Some(state.first_obj),
|
||||
second_obj: Some(state.second_obj),
|
||||
time: OffsetDateTime::now_utc(),
|
||||
}));
|
||||
}
|
||||
JobResult::CheckUpdate(state) => {
|
||||
self.view_state.check_update = Some(state);
|
||||
}
|
||||
JobResult::Update(state) => {
|
||||
if let Ok(mut guard) = self.relaunch_path.lock() {
|
||||
*guard = Some(state.exe_path);
|
||||
}
|
||||
self.should_relaunch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
let err = if let Some(msg) = err.downcast_ref::<&'static str>() {
|
||||
anyhow::Error::msg(*msg)
|
||||
} else if let Some(msg) = err.downcast_ref::<String>() {
|
||||
anyhow::Error::msg(msg.clone())
|
||||
} else {
|
||||
anyhow::Error::msg("Thread panicked")
|
||||
};
|
||||
let result = job.status.write();
|
||||
if let Ok(mut guard) = result {
|
||||
guard.error = Some(err);
|
||||
} else {
|
||||
drop(result);
|
||||
job.status = Arc::new(RwLock::new(JobStatus {
|
||||
title: "Error".to_string(),
|
||||
progress_percent: 0.0,
|
||||
progress_items: None,
|
||||
status: "".to_string(),
|
||||
error: Some(err),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
115
src/diff.rs
115
src/diff.rs
|
@ -211,25 +211,25 @@ fn address_eq(left: &ObjSymbol, right: &ObjSymbol) -> bool {
|
|||
}
|
||||
|
||||
fn reloc_eq(left_reloc: Option<&ObjReloc>, right_reloc: Option<&ObjReloc>) -> bool {
|
||||
if let (Some(left), Some(right)) = (left_reloc, right_reloc) {
|
||||
if left.kind != right.kind {
|
||||
return false;
|
||||
let (Some(left), Some(right)) = (left_reloc, right_reloc) else {
|
||||
return false;
|
||||
};
|
||||
if left.kind != right.kind {
|
||||
return false;
|
||||
}
|
||||
|
||||
let name_matches = left.target.name == right.target.name;
|
||||
match (&left.target_section, &right.target_section) {
|
||||
(Some(sl), Some(sr)) => {
|
||||
// Match if section and name or address match
|
||||
sl == sr && (name_matches || address_eq(&left.target, &right.target))
|
||||
}
|
||||
let name_matches = left.target.name == right.target.name;
|
||||
match (&left.target_section, &right.target_section) {
|
||||
(Some(sl), Some(sr)) => {
|
||||
// Match if section and name or address match
|
||||
sl == sr && (name_matches || address_eq(&left.target, &right.target))
|
||||
}
|
||||
(Some(_), None) => false,
|
||||
(None, Some(_)) => {
|
||||
// Match if possibly stripped weak symbol
|
||||
name_matches && right.target.flags.0.contains(ObjSymbolFlags::Weak)
|
||||
}
|
||||
(None, None) => name_matches,
|
||||
(Some(_), None) => false,
|
||||
(None, Some(_)) => {
|
||||
// Match if possibly stripped weak symbol
|
||||
name_matches && right.target.flags.0.contains(ObjSymbolFlags::Weak)
|
||||
}
|
||||
} else {
|
||||
false
|
||||
(None, None) => name_matches,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,48 +363,49 @@ fn find_symbol<'a>(symbols: &'a mut [ObjSymbol], name: &str) -> Option<&'a mut O
|
|||
|
||||
pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffConfig) -> Result<()> {
|
||||
for left_section in &mut left.sections {
|
||||
if let Some(right_section) = find_section(right, &left_section.name) {
|
||||
if left_section.kind == ObjSectionKind::Code {
|
||||
for left_symbol in &mut left_section.symbols {
|
||||
if let Some(right_symbol) =
|
||||
find_symbol(&mut right_section.symbols, &left_symbol.name)
|
||||
{
|
||||
left_symbol.diff_symbol = Some(right_symbol.name.clone());
|
||||
right_symbol.diff_symbol = Some(left_symbol.name.clone());
|
||||
diff_code(
|
||||
left.architecture,
|
||||
&left_section.data,
|
||||
&right_section.data,
|
||||
left_symbol,
|
||||
right_symbol,
|
||||
&left_section.relocations,
|
||||
&right_section.relocations,
|
||||
)?;
|
||||
} else {
|
||||
no_diff_code(
|
||||
left.architecture,
|
||||
&left_section.data,
|
||||
left_symbol,
|
||||
&left_section.relocations,
|
||||
)?;
|
||||
}
|
||||
let Some(right_section) = find_section(right, &left_section.name) else {
|
||||
continue;
|
||||
};
|
||||
if left_section.kind == ObjSectionKind::Code {
|
||||
for left_symbol in &mut left_section.symbols {
|
||||
if let Some(right_symbol) =
|
||||
find_symbol(&mut right_section.symbols, &left_symbol.name)
|
||||
{
|
||||
left_symbol.diff_symbol = Some(right_symbol.name.clone());
|
||||
right_symbol.diff_symbol = Some(left_symbol.name.clone());
|
||||
diff_code(
|
||||
left.architecture,
|
||||
&left_section.data,
|
||||
&right_section.data,
|
||||
left_symbol,
|
||||
right_symbol,
|
||||
&left_section.relocations,
|
||||
&right_section.relocations,
|
||||
)?;
|
||||
} else {
|
||||
no_diff_code(
|
||||
left.architecture,
|
||||
&left_section.data,
|
||||
left_symbol,
|
||||
&left_section.relocations,
|
||||
)?;
|
||||
}
|
||||
for right_symbol in &mut right_section.symbols {
|
||||
if right_symbol.instructions.is_empty() {
|
||||
no_diff_code(
|
||||
left.architecture,
|
||||
&right_section.data,
|
||||
right_symbol,
|
||||
&right_section.relocations,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
} else if left_section.kind == ObjSectionKind::Data {
|
||||
diff_data(left_section, right_section);
|
||||
// diff_data_symbols(left_section, right_section)?;
|
||||
} else if left_section.kind == ObjSectionKind::Bss {
|
||||
diff_bss_symbols(&mut left_section.symbols, &mut right_section.symbols)?;
|
||||
}
|
||||
for right_symbol in &mut right_section.symbols {
|
||||
if right_symbol.instructions.is_empty() {
|
||||
no_diff_code(
|
||||
left.architecture,
|
||||
&right_section.data,
|
||||
right_symbol,
|
||||
&right_section.relocations,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
} else if left_section.kind == ObjSectionKind::Data {
|
||||
diff_data(left_section, right_section);
|
||||
// diff_data_symbols(left_section, right_section)?;
|
||||
} else if left_section.kind == ObjSectionKind::Bss {
|
||||
diff_bss_symbols(&mut left_section.symbols, &mut right_section.symbols)?;
|
||||
}
|
||||
}
|
||||
diff_bss_symbols(&mut left.common, &mut right.common)?;
|
||||
|
|
|
@ -165,99 +165,91 @@ fn data_table_ui(
|
|||
|
||||
pub fn data_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool {
|
||||
let mut rebuild = false;
|
||||
if let (Some(result), Some(selected_symbol)) = (&view_state.build, &view_state.selected_symbol)
|
||||
{
|
||||
StripBuilder::new(ui)
|
||||
.size(Size::exact(20.0))
|
||||
.size(Size::exact(40.0))
|
||||
.size(Size::remainder())
|
||||
.vertical(|mut strip| {
|
||||
strip.strip(|builder| {
|
||||
builder.sizes(Size::remainder(), 2).horizontal(|mut strip| {
|
||||
strip.cell(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Back").clicked() {
|
||||
view_state.current_view = View::SymbolDiff;
|
||||
}
|
||||
});
|
||||
});
|
||||
strip.cell(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Build").clicked() {
|
||||
rebuild = true;
|
||||
}
|
||||
ui.scope(|ui| {
|
||||
ui.style_mut().override_text_style =
|
||||
Some(egui::TextStyle::Monospace);
|
||||
ui.style_mut().wrap = Some(false);
|
||||
if view_state
|
||||
.jobs
|
||||
.iter()
|
||||
.any(|job| job.job_type == Job::ObjDiff)
|
||||
{
|
||||
ui.label("Building...");
|
||||
} else {
|
||||
ui.label("Last built:");
|
||||
let format =
|
||||
format_description::parse("[hour]:[minute]:[second]")
|
||||
.unwrap();
|
||||
ui.label(
|
||||
result
|
||||
.time
|
||||
.to_offset(view_state.utc_offset)
|
||||
.format(&format)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
let (Some(result), Some(selected_symbol)) = (&view_state.build, &view_state.selected_symbol) else {
|
||||
return rebuild;
|
||||
};
|
||||
StripBuilder::new(ui)
|
||||
.size(Size::exact(20.0))
|
||||
.size(Size::exact(40.0))
|
||||
.size(Size::remainder())
|
||||
.vertical(|mut strip| {
|
||||
strip.strip(|builder| {
|
||||
builder.sizes(Size::remainder(), 2).horizontal(|mut strip| {
|
||||
strip.cell(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Back").clicked() {
|
||||
view_state.current_view = View::SymbolDiff;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
strip.strip(|builder| {
|
||||
builder.sizes(Size::remainder(), 2).horizontal(|mut strip| {
|
||||
strip.cell(|ui| {
|
||||
strip.cell(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Build").clicked() {
|
||||
rebuild = true;
|
||||
}
|
||||
ui.scope(|ui| {
|
||||
ui.style_mut().override_text_style =
|
||||
Some(egui::TextStyle::Monospace);
|
||||
ui.style_mut().wrap = Some(false);
|
||||
ui.colored_label(Color32::WHITE, &selected_symbol.symbol_name);
|
||||
ui.label("Diff target:");
|
||||
ui.separator();
|
||||
});
|
||||
});
|
||||
strip.cell(|ui| {
|
||||
ui.scope(|ui| {
|
||||
ui.style_mut().override_text_style =
|
||||
Some(egui::TextStyle::Monospace);
|
||||
ui.style_mut().wrap = Some(false);
|
||||
ui.label("");
|
||||
ui.label("Diff base:");
|
||||
ui.separator();
|
||||
if view_state.jobs.iter().any(|job| job.job_type == Job::ObjDiff) {
|
||||
ui.label("Building...");
|
||||
} else {
|
||||
ui.label("Last built:");
|
||||
let format =
|
||||
format_description::parse("[hour]:[minute]:[second]")
|
||||
.unwrap();
|
||||
ui.label(
|
||||
result
|
||||
.time
|
||||
.to_offset(view_state.utc_offset)
|
||||
.format(&format)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
strip.cell(|ui| {
|
||||
if let (Some(left_obj), Some(right_obj)) =
|
||||
(&result.first_obj, &result.second_obj)
|
||||
{
|
||||
let table = TableBuilder::new(ui)
|
||||
.striped(false)
|
||||
.cell_layout(egui::Layout::left_to_right(egui::Align::Min))
|
||||
.column(Size::relative(0.5))
|
||||
.column(Size::relative(0.5))
|
||||
.resizable(false);
|
||||
data_table_ui(
|
||||
table,
|
||||
left_obj,
|
||||
right_obj,
|
||||
selected_symbol,
|
||||
&view_state.view_config,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
strip.strip(|builder| {
|
||||
builder.sizes(Size::remainder(), 2).horizontal(|mut strip| {
|
||||
strip.cell(|ui| {
|
||||
ui.scope(|ui| {
|
||||
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
||||
ui.style_mut().wrap = Some(false);
|
||||
ui.colored_label(Color32::WHITE, &selected_symbol.symbol_name);
|
||||
ui.label("Diff target:");
|
||||
ui.separator();
|
||||
});
|
||||
});
|
||||
strip.cell(|ui| {
|
||||
ui.scope(|ui| {
|
||||
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
||||
ui.style_mut().wrap = Some(false);
|
||||
ui.label("");
|
||||
ui.label("Diff base:");
|
||||
ui.separator();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
strip.cell(|ui| {
|
||||
if let (Some(left_obj), Some(right_obj)) = (&result.first_obj, &result.second_obj) {
|
||||
let table = TableBuilder::new(ui)
|
||||
.striped(false)
|
||||
.cell_layout(egui::Layout::left_to_right(egui::Align::Min))
|
||||
.column(Size::relative(0.5))
|
||||
.column(Size::relative(0.5))
|
||||
.resizable(false);
|
||||
data_table_ui(
|
||||
table,
|
||||
left_obj,
|
||||
right_obj,
|
||||
selected_symbol,
|
||||
&view_state.view_config,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
rebuild
|
||||
}
|
||||
|
|
|
@ -251,46 +251,47 @@ fn asm_row_ui(ui: &mut egui::Ui, ins_diff: &ObjInsDiff, symbol: &ObjSymbol, conf
|
|||
ui.painter().rect_filled(ui.available_rect_before_wrap(), 0.0, ui.visuals().faint_bg_color);
|
||||
}
|
||||
let mut job = LayoutJob::default();
|
||||
if let Some(ins) = &ins_diff.ins {
|
||||
let base_color = match ins_diff.kind {
|
||||
ObjInsDiffKind::None | ObjInsDiffKind::OpMismatch | ObjInsDiffKind::ArgMismatch => {
|
||||
Color32::GRAY
|
||||
}
|
||||
ObjInsDiffKind::Replace => Color32::LIGHT_BLUE,
|
||||
ObjInsDiffKind::Delete => COLOR_RED,
|
||||
ObjInsDiffKind::Insert => Color32::GREEN,
|
||||
};
|
||||
let Some(ins) = &ins_diff.ins else {
|
||||
ui.label("");
|
||||
return;
|
||||
};
|
||||
|
||||
let base_color = match ins_diff.kind {
|
||||
ObjInsDiffKind::None | ObjInsDiffKind::OpMismatch | ObjInsDiffKind::ArgMismatch => {
|
||||
Color32::GRAY
|
||||
}
|
||||
ObjInsDiffKind::Replace => Color32::LIGHT_BLUE,
|
||||
ObjInsDiffKind::Delete => COLOR_RED,
|
||||
ObjInsDiffKind::Insert => Color32::GREEN,
|
||||
};
|
||||
write_text(
|
||||
&format!("{:<6}", format!("{:x}:", ins.address - symbol.address as u32)),
|
||||
base_color,
|
||||
&mut job,
|
||||
config.code_font.clone(),
|
||||
);
|
||||
if let Some(branch) = &ins_diff.branch_from {
|
||||
write_text(
|
||||
&format!("{:<6}", format!("{:x}:", ins.address - symbol.address as u32)),
|
||||
base_color,
|
||||
"~> ",
|
||||
config.diff_colors[branch.branch_idx % config.diff_colors.len()],
|
||||
&mut job,
|
||||
config.code_font.clone(),
|
||||
);
|
||||
if let Some(branch) = &ins_diff.branch_from {
|
||||
write_text(
|
||||
"~> ",
|
||||
config.diff_colors[branch.branch_idx % config.diff_colors.len()],
|
||||
&mut job,
|
||||
config.code_font.clone(),
|
||||
);
|
||||
} else {
|
||||
write_text(" ", base_color, &mut job, config.code_font.clone());
|
||||
}
|
||||
write_ins(ins, &ins_diff.kind, &ins_diff.arg_diff, symbol.address as u32, &mut job, config);
|
||||
if let Some(branch) = &ins_diff.branch_to {
|
||||
write_text(
|
||||
" ~>",
|
||||
config.diff_colors[branch.branch_idx % config.diff_colors.len()],
|
||||
&mut job,
|
||||
config.code_font.clone(),
|
||||
);
|
||||
}
|
||||
ui.add(Label::new(job).sense(Sense::click()))
|
||||
.on_hover_ui_at_pointer(|ui| ins_hover_ui(ui, ins))
|
||||
.context_menu(|ui| ins_context_menu(ui, ins));
|
||||
} else {
|
||||
ui.label("");
|
||||
write_text(" ", base_color, &mut job, config.code_font.clone());
|
||||
}
|
||||
write_ins(ins, &ins_diff.kind, &ins_diff.arg_diff, symbol.address as u32, &mut job, config);
|
||||
if let Some(branch) = &ins_diff.branch_to {
|
||||
write_text(
|
||||
" ~>",
|
||||
config.diff_colors[branch.branch_idx % config.diff_colors.len()],
|
||||
&mut job,
|
||||
config.code_font.clone(),
|
||||
);
|
||||
}
|
||||
ui.add(Label::new(job).sense(Sense::click()))
|
||||
.on_hover_ui_at_pointer(|ui| ins_hover_ui(ui, ins))
|
||||
.context_menu(|ui| ins_context_menu(ui, ins));
|
||||
}
|
||||
|
||||
fn asm_table_ui(
|
||||
|
@ -322,113 +323,105 @@ fn asm_table_ui(
|
|||
|
||||
pub fn function_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool {
|
||||
let mut rebuild = false;
|
||||
if let (Some(result), Some(selected_symbol)) = (&view_state.build, &view_state.selected_symbol)
|
||||
{
|
||||
StripBuilder::new(ui)
|
||||
.size(Size::exact(20.0))
|
||||
.size(Size::exact(40.0))
|
||||
.size(Size::remainder())
|
||||
.vertical(|mut strip| {
|
||||
strip.strip(|builder| {
|
||||
builder.sizes(Size::remainder(), 2).horizontal(|mut strip| {
|
||||
strip.cell(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Back").clicked() {
|
||||
view_state.current_view = View::SymbolDiff;
|
||||
}
|
||||
});
|
||||
});
|
||||
strip.cell(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Build").clicked() {
|
||||
rebuild = true;
|
||||
}
|
||||
ui.scope(|ui| {
|
||||
ui.style_mut().override_text_style =
|
||||
Some(egui::TextStyle::Monospace);
|
||||
ui.style_mut().wrap = Some(false);
|
||||
if view_state
|
||||
.jobs
|
||||
.iter()
|
||||
.any(|job| job.job_type == Job::ObjDiff)
|
||||
{
|
||||
ui.label("Building...");
|
||||
} else {
|
||||
ui.label("Last built:");
|
||||
let format =
|
||||
format_description::parse("[hour]:[minute]:[second]")
|
||||
.unwrap();
|
||||
ui.label(
|
||||
result
|
||||
.time
|
||||
.to_offset(view_state.utc_offset)
|
||||
.format(&format)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
let (Some(result), Some(selected_symbol)) = (&view_state.build, &view_state.selected_symbol) else {
|
||||
return rebuild;
|
||||
};
|
||||
StripBuilder::new(ui)
|
||||
.size(Size::exact(20.0))
|
||||
.size(Size::exact(40.0))
|
||||
.size(Size::remainder())
|
||||
.vertical(|mut strip| {
|
||||
strip.strip(|builder| {
|
||||
builder.sizes(Size::remainder(), 2).horizontal(|mut strip| {
|
||||
strip.cell(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Back").clicked() {
|
||||
view_state.current_view = View::SymbolDiff;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
strip.strip(|builder| {
|
||||
builder.sizes(Size::remainder(), 2).horizontal(|mut strip| {
|
||||
let demangled = demangle(&selected_symbol.symbol_name, &Default::default());
|
||||
strip.cell(|ui| {
|
||||
strip.cell(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Build").clicked() {
|
||||
rebuild = true;
|
||||
}
|
||||
ui.scope(|ui| {
|
||||
ui.style_mut().override_text_style =
|
||||
Some(egui::TextStyle::Monospace);
|
||||
ui.style_mut().wrap = Some(false);
|
||||
ui.colored_label(
|
||||
Color32::WHITE,
|
||||
demangled.as_ref().unwrap_or(&selected_symbol.symbol_name),
|
||||
);
|
||||
ui.label("Diff target:");
|
||||
ui.separator();
|
||||
});
|
||||
});
|
||||
strip.cell(|ui| {
|
||||
ui.scope(|ui| {
|
||||
ui.style_mut().override_text_style =
|
||||
Some(egui::TextStyle::Monospace);
|
||||
ui.style_mut().wrap = Some(false);
|
||||
if let Some(match_percent) = result
|
||||
.second_obj
|
||||
.as_ref()
|
||||
.and_then(|obj| find_symbol(obj, selected_symbol))
|
||||
.and_then(|symbol| symbol.match_percent)
|
||||
{
|
||||
ui.colored_label(
|
||||
match_color_for_symbol(match_percent),
|
||||
&format!("{match_percent:.0}%"),
|
||||
if view_state.jobs.iter().any(|job| job.job_type == Job::ObjDiff) {
|
||||
ui.label("Building...");
|
||||
} else {
|
||||
ui.label("Last built:");
|
||||
let format =
|
||||
format_description::parse("[hour]:[minute]:[second]")
|
||||
.unwrap();
|
||||
ui.label(
|
||||
result
|
||||
.time
|
||||
.to_offset(view_state.utc_offset)
|
||||
.format(&format)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
ui.label("Diff base:");
|
||||
ui.separator();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
strip.cell(|ui| {
|
||||
if let (Some(left_obj), Some(right_obj)) =
|
||||
(&result.first_obj, &result.second_obj)
|
||||
{
|
||||
let table = TableBuilder::new(ui)
|
||||
.striped(false)
|
||||
.cell_layout(egui::Layout::left_to_right(egui::Align::Min))
|
||||
.column(Size::relative(0.5))
|
||||
.column(Size::relative(0.5))
|
||||
.resizable(false);
|
||||
asm_table_ui(
|
||||
table,
|
||||
left_obj,
|
||||
right_obj,
|
||||
selected_symbol,
|
||||
&view_state.view_config,
|
||||
);
|
||||
}
|
||||
});
|
||||
strip.strip(|builder| {
|
||||
builder.sizes(Size::remainder(), 2).horizontal(|mut strip| {
|
||||
let demangled = demangle(&selected_symbol.symbol_name, &Default::default());
|
||||
strip.cell(|ui| {
|
||||
ui.scope(|ui| {
|
||||
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
||||
ui.style_mut().wrap = Some(false);
|
||||
ui.colored_label(
|
||||
Color32::WHITE,
|
||||
demangled.as_ref().unwrap_or(&selected_symbol.symbol_name),
|
||||
);
|
||||
ui.label("Diff target:");
|
||||
ui.separator();
|
||||
});
|
||||
});
|
||||
strip.cell(|ui| {
|
||||
ui.scope(|ui| {
|
||||
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
||||
ui.style_mut().wrap = Some(false);
|
||||
if let Some(match_percent) = result
|
||||
.second_obj
|
||||
.as_ref()
|
||||
.and_then(|obj| find_symbol(obj, selected_symbol))
|
||||
.and_then(|symbol| symbol.match_percent)
|
||||
{
|
||||
ui.colored_label(
|
||||
match_color_for_symbol(match_percent),
|
||||
&format!("{match_percent:.0}%"),
|
||||
);
|
||||
}
|
||||
ui.label("Diff base:");
|
||||
ui.separator();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
strip.cell(|ui| {
|
||||
if let (Some(left_obj), Some(right_obj)) = (&result.first_obj, &result.second_obj) {
|
||||
let table = TableBuilder::new(ui)
|
||||
.striped(false)
|
||||
.cell_layout(egui::Layout::left_to_right(egui::Align::Min))
|
||||
.column(Size::relative(0.5))
|
||||
.column(Size::relative(0.5))
|
||||
.resizable(false);
|
||||
asm_table_ui(
|
||||
table,
|
||||
left_obj,
|
||||
right_obj,
|
||||
selected_symbol,
|
||||
&view_state.view_config,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
rebuild
|
||||
}
|
||||
|
|
|
@ -7,46 +7,47 @@ pub fn jobs_ui(ui: &mut egui::Ui, view_state: &mut ViewState) {
|
|||
|
||||
let mut remove_job: Option<usize> = None;
|
||||
for (idx, job) in view_state.jobs.iter_mut().enumerate() {
|
||||
if let Ok(status) = job.status.read() {
|
||||
ui.group(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(&status.title);
|
||||
if ui.small_button("✖").clicked() {
|
||||
if job.handle.is_some() {
|
||||
job.should_remove = true;
|
||||
if let Err(e) = job.cancel.send(()) {
|
||||
eprintln!("Failed to cancel job: {e:?}");
|
||||
}
|
||||
} else {
|
||||
remove_job = Some(idx);
|
||||
let Ok(status) = job.status.read() else {
|
||||
continue;
|
||||
};
|
||||
ui.group(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(&status.title);
|
||||
if ui.small_button("✖").clicked() {
|
||||
if job.handle.is_some() {
|
||||
job.should_remove = true;
|
||||
if let Err(e) = job.cancel.send(()) {
|
||||
eprintln!("Failed to cancel job: {e:?}");
|
||||
}
|
||||
}
|
||||
});
|
||||
let mut bar = ProgressBar::new(status.progress_percent);
|
||||
if let Some(items) = &status.progress_items {
|
||||
bar = bar.text(format!("{} / {}", items[0], items[1]));
|
||||
}
|
||||
bar.ui(ui);
|
||||
const STATUS_LENGTH: usize = 80;
|
||||
if let Some(err) = &status.error {
|
||||
let err_string = err.to_string();
|
||||
ui.colored_label(
|
||||
Color32::from_rgb(255, 0, 0),
|
||||
if err_string.len() > STATUS_LENGTH - 10 {
|
||||
format!("Error: {}...", &err_string[0..STATUS_LENGTH - 10])
|
||||
} else {
|
||||
format!("Error: {:width$}", err_string, width = STATUS_LENGTH - 7)
|
||||
},
|
||||
);
|
||||
} else {
|
||||
ui.label(if status.status.len() > STATUS_LENGTH - 3 {
|
||||
format!("{}...", &status.status[0..STATUS_LENGTH - 3])
|
||||
} else {
|
||||
format!("{:width$}", &status.status, width = STATUS_LENGTH)
|
||||
});
|
||||
remove_job = Some(idx);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
let mut bar = ProgressBar::new(status.progress_percent);
|
||||
if let Some(items) = &status.progress_items {
|
||||
bar = bar.text(format!("{} / {}", items[0], items[1]));
|
||||
}
|
||||
bar.ui(ui);
|
||||
const STATUS_LENGTH: usize = 80;
|
||||
if let Some(err) = &status.error {
|
||||
let err_string = err.to_string();
|
||||
ui.colored_label(
|
||||
Color32::from_rgb(255, 0, 0),
|
||||
if err_string.len() > STATUS_LENGTH - 10 {
|
||||
format!("Error: {}...", &err_string[0..STATUS_LENGTH - 10])
|
||||
} else {
|
||||
format!("Error: {:width$}", err_string, width = STATUS_LENGTH - 7)
|
||||
},
|
||||
);
|
||||
} else {
|
||||
ui.label(if status.status.len() > STATUS_LENGTH - 3 {
|
||||
format!("{}...", &status.status[0..STATUS_LENGTH - 3])
|
||||
} else {
|
||||
format!("{:width$}", &status.status, width = STATUS_LENGTH)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(idx) = remove_job {
|
||||
|
|
Loading…
Reference in New Issue