hex_patch/app/asm/
assembly_line.rs1use ratatui::text::{Line, Span};
2
3use crate::{
4 app::{settings::color_settings::ColorSettings, App},
5 headers::Header,
6};
7
8use super::{instruction_tag::InstructionTag, section_tag::SectionTag};
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum AssemblyLine {
12 Instruction(InstructionTag),
13 SectionTag(SectionTag),
14}
15
16impl AssemblyLine {
17 pub fn file_address(&self) -> u64 {
18 match self {
19 AssemblyLine::Instruction(instruction) => instruction.file_address,
20 AssemblyLine::SectionTag(section) => section.file_address,
21 }
22 }
23
24 pub fn virtual_address(&self) -> u64 {
25 match self {
26 AssemblyLine::Instruction(instruction) => instruction.instruction.ip(),
27 AssemblyLine::SectionTag(section) => section.virtual_address,
28 }
29 }
30
31 pub fn len(&self) -> usize {
32 match self {
33 AssemblyLine::Instruction(instruction) => instruction.instruction.len(),
34 AssemblyLine::SectionTag(section) => section.size,
35 }
36 }
37
38 pub fn is_empty(&self) -> bool {
39 match self {
40 AssemblyLine::Instruction(instruction) => instruction.instruction.is_empty(),
41 AssemblyLine::SectionTag(section) => section.size == 0,
42 }
43 }
44
45 pub fn to_line(
46 &self,
47 color_settings: &ColorSettings,
48 current_byte_index: usize,
49 header: &Header,
50 address_min_width: usize,
51 ) -> Line {
52 match self {
53 AssemblyLine::Instruction(instruction) => {
54 let selected = current_byte_index >= instruction.file_address as usize
55 && current_byte_index
56 < instruction.file_address as usize + instruction.instruction.len();
57 App::instruction_to_line(
58 color_settings,
59 instruction,
60 selected,
61 header,
62 address_min_width,
63 )
64 }
65 AssemblyLine::SectionTag(section) => {
66 let selected = current_byte_index >= section.file_address as usize
67 && current_byte_index < section.file_address as usize + section.size;
68 let mut line = Line::default();
69 let address_style = if selected {
70 color_settings.assembly_selected
71 } else {
72 color_settings.assembly_address
73 };
74 line.spans.push(Span::styled(
75 format!("{:>address_min_width$X}", section.file_address),
76 address_style,
77 ));
78 line.spans.push(Span::raw(" "));
79 line.spans.push(Span::styled(
80 format!("[{} ({}B)]", section.name, section.size),
81 color_settings.assembly_section,
82 ));
83 line.spans.push(Span::styled(
84 format!(" @{:X}", section.virtual_address),
85 color_settings.assembly_virtual_address,
86 ));
87 line
88 }
89 }
90 }
91
92 pub fn is_same_instruction(&self, other: &AssemblyLine) -> bool {
93 match (self, other) {
94 (
95 AssemblyLine::Instruction(instruction),
96 AssemblyLine::Instruction(other_instruction),
97 ) => {
98 instruction.instruction.bytes == other_instruction.instruction.bytes
99 && instruction.instruction.virtual_address
100 == other_instruction.instruction.virtual_address
101 }
102 _ => false,
103 }
104 }
105}