iced_x86/formatter/
symres.rs

1// SPDX-License-Identifier: MIT
2// Copyright (C) 2018-present iced project and contributors
3
4use crate::*;
5use alloc::string::String;
6use alloc::vec::Vec;
7
8/// Used by a [`Formatter`] to resolve symbols
9///
10/// [`Formatter`]: trait.Formatter.html
11pub trait SymbolResolver {
12	/// Tries to resolve a symbol
13	///
14	/// # Arguments
15	///
16	/// - `instruction`: Instruction
17	/// - `operand`: Operand number, 0-based. This is a formatter operand and isn't necessarily the same as an instruction operand.
18	/// - `instruction_operand`: Instruction operand number, 0-based, or `None` if it's an operand created by the formatter.
19	/// - `address`: Address
20	/// - `address_size`: Size of `address` in bytes (eg. 1, 2, 4 or 8)
21	fn symbol(
22		&mut self, instruction: &Instruction, operand: u32, instruction_operand: Option<u32>, address: u64, address_size: u32,
23	) -> Option<SymbolResult<'_>>;
24}
25
26/// Contains a `&'a str` or a `String`
27#[derive(Debug, Clone, Eq, PartialEq, Hash)]
28pub enum SymResString<'a> {
29	/// Contains a `&'a str`
30	Str(#[doc = "The str"] &'a str),
31	/// Contains a `String`
32	String(#[doc = "The string"] String),
33}
34impl Default for SymResString<'_> {
35	#[must_use]
36	#[inline]
37	fn default() -> Self {
38		SymResString::Str("")
39	}
40}
41impl SymResString<'_> {
42	pub(super) fn to_owned<'b>(self) -> SymResString<'b> {
43		match self {
44			SymResString::Str(s) => SymResString::String(String::from(s)),
45			SymResString::String(s) => SymResString::String(s),
46		}
47	}
48
49	pub(super) fn to_owned2<'b>(&self) -> SymResString<'b> {
50		match self {
51			&SymResString::Str(s) => SymResString::String(String::from(s)),
52			SymResString::String(s) => SymResString::String(s.clone()),
53		}
54	}
55}
56
57/// Contains text and colors
58#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
59pub struct SymResTextPart<'a> {
60	/// Text
61	pub text: SymResString<'a>,
62	/// Color
63	pub color: FormatterTextKind,
64}
65
66impl<'a> SymResTextPart<'a> {
67	/// Constructor
68	///
69	/// # Arguments
70	///
71	/// - `text`: Text
72	/// - `color`: Color
73	#[must_use]
74	#[inline]
75	pub const fn new(text: &'a str, color: FormatterTextKind) -> Self {
76		Self { text: SymResString::Str(text), color }
77	}
78
79	/// Constructor
80	///
81	/// # Arguments
82	///
83	/// - `text`: Text
84	/// - `color`: Color
85	#[must_use]
86	#[inline]
87	pub const fn with_string(text: String, color: FormatterTextKind) -> Self {
88		Self { text: SymResString::String(text), color }
89	}
90
91	pub(super) fn to_owned<'b>(self) -> SymResTextPart<'b> {
92		SymResTextPart { text: self.text.to_owned(), color: self.color }
93	}
94
95	pub(super) fn to_owned2<'b>(&self) -> SymResTextPart<'b> {
96		SymResTextPart { text: self.text.to_owned2(), color: self.color }
97	}
98}
99
100/// Contains one or more [`SymResTextPart`]s (text and color)
101///
102/// [`SymResTextPart`]: struct.SymResTextPart.html
103#[derive(Debug, Clone, Eq, PartialEq, Hash)]
104pub enum SymResTextInfo<'a> {
105	/// Text and color
106	Text(#[doc = "Text and color"] SymResTextPart<'a>),
107	/// Text and color (vector)
108	TextVec(#[doc = "Text and color"] &'a [SymResTextPart<'a>]),
109}
110
111impl<'a> SymResTextInfo<'a> {
112	/// Constructor
113	///
114	/// # Arguments
115	///
116	/// - `text`: Text
117	/// - `color`: Color
118	#[must_use]
119	#[inline]
120	pub const fn new(text: &'a str, color: FormatterTextKind) -> Self {
121		SymResTextInfo::Text(SymResTextPart::new(text, color))
122	}
123
124	/// Constructor
125	///
126	/// # Arguments
127	///
128	/// - `text`: Text
129	/// - `color`: Color
130	#[must_use]
131	#[inline]
132	pub const fn with_string(text: String, color: FormatterTextKind) -> Self {
133		SymResTextInfo::Text(SymResTextPart::with_string(text, color))
134	}
135
136	/// Constructor
137	///
138	/// # Arguments
139	///
140	/// - `text`: Text
141	#[must_use]
142	#[inline]
143	pub const fn with_text(text: SymResTextPart<'a>) -> Self {
144		SymResTextInfo::Text(text)
145	}
146
147	/// Constructor
148	///
149	/// # Arguments
150	///
151	/// - `text`: Text
152	#[must_use]
153	#[inline]
154	pub const fn with_vec(text: &'a [SymResTextPart<'a>]) -> Self {
155		SymResTextInfo::TextVec(text)
156	}
157
158	pub(super) fn to_owned<'b>(self, vec: &'b mut Vec<SymResTextPart<'b>>) -> SymResTextInfo<'b> {
159		match self {
160			SymResTextInfo::Text(part) => SymResTextInfo::Text(part.to_owned()),
161			SymResTextInfo::TextVec(parts) => {
162				vec.clear();
163				vec.extend(parts.iter().map(SymResTextPart::to_owned2));
164				SymResTextInfo::TextVec(vec)
165			}
166		}
167	}
168}
169
170/// Created by a [`SymbolResolver`]
171///
172/// [`SymbolResolver`]: trait.SymbolResolver.html
173#[derive(Debug, Clone, Eq, PartialEq, Hash)]
174pub struct SymbolResult<'a> {
175	/// The address of the symbol
176	pub address: u64,
177
178	/// Contains the symbol
179	pub text: SymResTextInfo<'a>,
180
181	/// Symbol flags, see [`SymbolFlags`]
182	///
183	/// [`SymbolFlags`]: struct.SymbolFlags.html
184	pub flags: u32,
185
186	/// Symbol size or `None`
187	pub symbol_size: Option<MemorySize>,
188}
189
190impl<'a> SymbolResult<'a> {
191	const DEFAULT_KIND: FormatterTextKind = FormatterTextKind::Label;
192
193	/// Constructor
194	///
195	/// # Arguments
196	///
197	/// - `address`: The address of the symbol
198	/// - `text`: Symbol
199	#[must_use]
200	#[inline]
201	pub const fn with_str(address: u64, text: &'a str) -> Self {
202		Self { address, text: SymResTextInfo::new(text, SymbolResult::DEFAULT_KIND), flags: SymbolFlags::NONE, symbol_size: None }
203	}
204
205	/// Constructor
206	///
207	/// # Arguments
208	///
209	/// - `address`: The address of the symbol
210	/// - `text`: Symbol
211	/// - `size`: Symbol size
212	#[must_use]
213	#[inline]
214	pub const fn with_str_size(address: u64, text: &'a str, size: MemorySize) -> Self {
215		Self { address, text: SymResTextInfo::new(text, SymbolResult::DEFAULT_KIND), flags: SymbolFlags::NONE, symbol_size: Some(size) }
216	}
217
218	/// Constructor
219	///
220	/// # Arguments
221	///
222	/// - `address`: The address of the symbol
223	/// - `text`: Symbol
224	/// - `color`: Color
225	#[must_use]
226	#[inline]
227	pub const fn with_str_kind(address: u64, text: &'a str, color: FormatterTextKind) -> Self {
228		Self { address, text: SymResTextInfo::new(text, color), flags: SymbolFlags::NONE, symbol_size: None }
229	}
230
231	/// Constructor
232	///
233	/// # Arguments
234	///
235	/// - `address`: The address of the symbol
236	/// - `text`: Symbol
237	/// - `color`: Color
238	/// - `flags`: Symbol flags, see [`SymbolFlags`]
239	///
240	/// [`SymbolFlags`]: struct.SymbolFlags.html
241	#[must_use]
242	#[inline]
243	pub const fn with_str_kind_flags(address: u64, text: &'a str, color: FormatterTextKind, flags: u32) -> Self {
244		Self { address, text: SymResTextInfo::new(text, color), flags, symbol_size: None }
245	}
246
247	/// Constructor
248	///
249	/// # Arguments
250	///
251	/// - `address`: The address of the symbol
252	/// - `text`: Symbol
253	#[must_use]
254	#[inline]
255	pub const fn with_string(address: u64, text: String) -> Self {
256		Self { address, text: SymResTextInfo::with_string(text, SymbolResult::DEFAULT_KIND), flags: SymbolFlags::NONE, symbol_size: None }
257	}
258
259	/// Constructor
260	///
261	/// # Arguments
262	///
263	/// - `address`: The address of the symbol
264	/// - `text`: Symbol
265	/// - `size`: Symbol size
266	#[must_use]
267	#[inline]
268	pub const fn with_string_size(address: u64, text: String, size: MemorySize) -> Self {
269		Self { address, text: SymResTextInfo::with_string(text, SymbolResult::DEFAULT_KIND), flags: SymbolFlags::NONE, symbol_size: Some(size) }
270	}
271
272	/// Constructor
273	///
274	/// # Arguments
275	///
276	/// - `address`: The address of the symbol
277	/// - `text`: Symbol
278	/// - `color`: Color
279	#[must_use]
280	#[inline]
281	pub const fn with_string_kind(address: u64, text: String, color: FormatterTextKind) -> Self {
282		Self { address, text: SymResTextInfo::with_string(text, color), flags: SymbolFlags::NONE, symbol_size: None }
283	}
284
285	/// Constructor
286	///
287	/// # Arguments
288	///
289	/// - `address`: The address of the symbol
290	/// - `text`: Symbol
291	/// - `color`: Color
292	/// - `flags`: Symbol flags, see [`SymbolFlags`]
293	///
294	/// [`SymbolFlags`]: struct.SymbolFlags.html
295	#[must_use]
296	#[inline]
297	pub const fn with_string_kind_flags(address: u64, text: String, color: FormatterTextKind, flags: u32) -> Self {
298		Self { address, text: SymResTextInfo::with_string(text, color), flags, symbol_size: None }
299	}
300
301	/// Constructor
302	///
303	/// # Arguments
304	///
305	/// - `address`: The address of the symbol
306	/// - `text`: Symbol
307	#[must_use]
308	#[inline]
309	pub const fn with_text(address: u64, text: SymResTextInfo<'a>) -> Self {
310		Self { address, text, flags: SymbolFlags::NONE, symbol_size: None }
311	}
312
313	/// Constructor
314	///
315	/// # Arguments
316	///
317	/// - `address`: The address of the symbol
318	/// - `text`: Symbol
319	/// - `size`: Symbol size
320	#[must_use]
321	#[inline]
322	pub const fn with_text_size(address: u64, text: SymResTextInfo<'a>, size: MemorySize) -> Self {
323		Self { address, text, flags: SymbolFlags::NONE, symbol_size: Some(size) }
324	}
325
326	/// Constructor
327	///
328	/// # Arguments
329	///
330	/// - `address`: The address of the symbol
331	/// - `text`: Symbol
332	/// - `flags`: Symbol flags, see [`SymbolFlags`]
333	///
334	/// [`SymbolFlags`]: struct.SymbolFlags.html
335	#[must_use]
336	#[inline]
337	pub const fn with_text_flags(address: u64, text: SymResTextInfo<'a>, flags: u32) -> Self {
338		Self { address, text, flags, symbol_size: None }
339	}
340
341	/// Constructor
342	///
343	/// # Arguments
344	///
345	/// - `address`: The address of the symbol
346	/// - `text`: Symbol
347	/// - `flags`: Symbol flags, see [`SymbolFlags`]
348	/// - `size`: Symbol size
349	///
350	/// [`SymbolFlags`]: struct.SymbolFlags.html
351	#[must_use]
352	#[inline]
353	pub const fn with_text_flags_size(address: u64, text: SymResTextInfo<'a>, flags: u32, size: MemorySize) -> Self {
354		Self { address, text, flags, symbol_size: Some(size) }
355	}
356
357	pub(super) fn to_owned<'b>(self, vec: &'b mut Vec<SymResTextPart<'b>>) -> SymbolResult<'b> {
358		SymbolResult { address: self.address, text: self.text.to_owned(vec), flags: self.flags, symbol_size: self.symbol_size }
359	}
360}