New type query function using TypeInfo

This commit is contained in:
Manuel Cillero 2024-04-12 21:45:13 +02:00
parent 4b1e34487d
commit 5e457eed3d
8 changed files with 104 additions and 46 deletions

View file

@ -5,25 +5,86 @@ use crate::trace;
use std::io;
use std::path::PathBuf;
pub enum TypeInfo {
FullName,
ShortName,
NameFrom(isize),
NameTo(isize),
PartialName(isize, isize),
}
impl TypeInfo {
pub fn of<T: ?Sized>(&self) -> &'static str {
let type_name = std::any::type_name::<T>();
match self {
TypeInfo::FullName => type_name,
TypeInfo::ShortName => Self::partial(type_name, -1, None),
TypeInfo::NameFrom(start) => Self::partial(type_name, *start, None),
TypeInfo::NameTo(end) => Self::partial(type_name, 0, Some(*end)),
TypeInfo::PartialName(start, end) => Self::partial(type_name, *start, Some(*end)),
}
}
fn partial(type_name: &'static str, start: isize, end: Option<isize>) -> &'static str {
let maxlen = type_name.len();
let mut segments = Vec::new();
let mut segment_start = 0; // Start position of the current segment.
let mut angle_brackets = 0; // Counter for tracking '<' and '>'.
let mut previous_char = '\0'; // Initializes to a null character, no previous character.
for (idx, c) in type_name.char_indices() {
match c {
':' if angle_brackets == 0 => {
if previous_char == ':' {
if segment_start < idx - 1 {
segments.push((segment_start, idx - 1)); // Do not include last '::'.
}
segment_start = idx + 1; // Next segment starts after '::'.
}
}
'<' => angle_brackets += 1,
'>' => angle_brackets -= 1,
_ => {}
}
previous_char = c;
}
// Include the last segment if there's any.
if segment_start < maxlen {
segments.push((segment_start, maxlen));
}
// Calculates the start position.
let start_pos = segments
.get(if start >= 0 {
start as usize
} else {
segments.len() - start.abs() as usize
})
.map_or(0, |&(s, _)| s);
// Calculates the end position.
let end_pos = segments
.get(if let Some(end) = end {
if end >= 0 {
end as usize
} else {
segments.len() - end.abs() as usize
}
} else {
segments.len() - 1
})
.map_or(maxlen, |&(_, e)| e);
// Returns the partial string based on the calculated positions.
&type_name[start_pos..end_pos]
}
}
// *************************************************************************************************
// FUNCTIONS HELPERS.
// *************************************************************************************************
pub fn partial_type_name(type_name: &'static str, last: usize) -> &'static str {
if last == 0 {
return type_name;
}
let positions: Vec<_> = type_name.rmatch_indices("::").collect();
if positions.len() < last {
return type_name;
}
&type_name[(positions[last - 1].0 + 2)..]
}
pub fn single_type_name<T: ?Sized>() -> &'static str {
partial_type_name(std::any::type_name::<T>(), 1)
}
pub fn absolute_dir(
root_path: impl Into<String>,
relative_path: impl Into<String>,