Skip to content

Commit

Permalink
chore(infra_utils): add short_module_name util
Browse files Browse the repository at this point in the history
commit-id:712643b5
  • Loading branch information
Itay-Tsabary-Starkware committed Dec 17, 2024
1 parent 97b0f33 commit 8bb781b
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
1 change: 1 addition & 0 deletions crates/infra_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ pub mod command;
pub mod path;
pub mod run_until;
pub mod tracing;
pub mod type_name;
83 changes: 83 additions & 0 deletions crates/infra_utils/src/type_name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use std::any::type_name;

#[cfg(test)]
#[path = "type_name_test.rs"]
mod type_name_test;

pub fn short_type_name<T: ?Sized>() -> String {
let full_name = type_name::<T>();
truncate_type(full_name)
}

/// Truncates a fully qualified Rust type name by removing module paths, leaving only the type
/// name and its generic parameters.
///
/// # Description
/// This function processes a Rust type string containing module paths, type names, and generic
/// parameters, such as:
/// ```text
/// starknet_sequencer_infra::component_client::local_component_client::LocalComponentClient<starknet_batcher_types::communication::BatcherRequest, starknet_batcher_types::communication::BatcherResponse>
/// ```
/// It removes the module paths (`::module_name`) and keeps only the type name and its
/// generic parameters:
/// ```text
/// LocalComponentClient<BatcherRequest, BatcherResponse>
/// ```
///
/// # Algorithm
/// - Iterates over the input string using a character iterator with indices.
/// - When encountering two consecutive colons (`::`), skips the preceding module path.
/// - When encountering delimiters (`<`, `,`, `>`), slices the substring from the current segment
/// start to the current index, appends it to the result, and resets the segment start.
/// - At the end, appends the remaining segment to the result.
///
/// # Examples
/// ```rust,ignore
/// let input = "a::b::c::Type<d::e::Inner, f::g::Other>";
/// let output = truncate_type(input);
/// assert_eq!(output, "Type<Inner, Other>");
/// ```
///
/// # Panics
/// This function does not panic as it only operates on valid UTF-8 strings.
///
/// # Complexity
/// The function runs in O(n) time, where `n` is the length of the input string.
///
/// # Limitations
/// - The function assumes well-formed Rust type strings. Incorrectly formatted input may yield
/// unexpected results.
///
/// # Returns
/// A new `String` with module paths removed and generic parameters preserved.
fn truncate_type(input: &str) -> String {
let mut result = String::new();
let mut segment_start = 0;
let mut iter = input.char_indices().peekable();

while let Some((index, c)) = iter.next() {
if c == ':' {
if let Some((_, next_char)) = iter.peek() {
if *next_char == ':' {
// Skip the next ':'
iter.next();
segment_start = index + 2; // Move `segment_start` after the second ':'
}
}
} else if c == '<' || c == ',' || c == '>' {
// Add the slice from `segment_start` to the current index to the result
if segment_start < index {
result.push_str(input[segment_start..index].trim());
result.push(c);
}
segment_start = index + 1; // Move `segment_start` after the current delimiter
}
}

// Add the final slice from `segment_start` to the end
if segment_start < input.len() {
result.push_str(input[segment_start..].trim());
}

result
}
23 changes: 23 additions & 0 deletions crates/infra_utils/src/type_name_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use pretty_assertions::assert_eq;

use crate::type_name::short_type_name;

struct TestStruct {}

struct GenericTestStruct<T> {
_placeholder: T,
}

mod submodule {
pub struct SubmoduleStruct {}
}

#[test]
fn resolve_project_relative_path_success() {
assert_eq!(short_type_name::<TestStruct>().as_str(), "TestStruct");
assert_eq!(short_type_name::<GenericTestStruct<u32>>().as_str(), "GenericTestStruct<u32>");
assert_eq!(
short_type_name::<GenericTestStruct<submodule::SubmoduleStruct>>().as_str(),
"GenericTestStruct<SubmoduleStruct>"
);
}

0 comments on commit 8bb781b

Please sign in to comment.