diff --git a/src/core.rs b/src/core.rs index f1ddc8b2..698aa1cd 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,6 +1,6 @@ //! Key types and functions for creating actions, components, packages, and themes. -use crate::util; +use crate::util::TypeInfo; use std::any::Any; @@ -8,7 +8,7 @@ use std::any::Any; pub trait AnyBase: Any { fn type_name(&self) -> &'static str; - fn single_name(&self) -> &'static str; + fn short_name(&self) -> &'static str; fn as_any_ref(&self) -> &dyn Any; @@ -18,12 +18,12 @@ pub trait AnyBase: Any { impl AnyBase for T { #[inline(always)] fn type_name(&self) -> &'static str { - std::any::type_name::() + TypeInfo::FullName.of::() } #[inline(always)] - fn single_name(&self) -> &'static str { - util::single_type_name::() + fn short_name(&self) -> &'static str { + TypeInfo::ShortName.of::() } #[inline(always)] diff --git a/src/core/component/context.rs b/src/core/component/context.rs index ed47ff56..89ed78a0 100644 --- a/src/core/component/context.rs +++ b/src/core/component/context.rs @@ -1,13 +1,14 @@ use crate::base::component::add_base_assets; +use crate::concat_string; use crate::core::component::AnyOp; -use crate::core::theme::all::{theme_by_single_name, THEME_DEFAULT}; +use crate::core::theme::all::{theme_by_short_name, THEME_DEFAULT}; use crate::core::theme::{ComponentsInRegions, ThemeRef}; use crate::html::{html, Markup}; use crate::html::{Assets, HeadScript, HeadStyles, JavaScript, StyleSheet}; use crate::html::{ClassesOp, OptionClasses, OptionId}; use crate::locale::{LanguageIdentifier, LANGID_DEFAULT}; use crate::service::HttpRequest; -use crate::{concat_string, util}; +use crate::util::TypeInfo; use std::collections::HashMap; use std::str::FromStr; @@ -78,7 +79,7 @@ impl Context { self.langid = langid; } AssetsOp::Theme(theme_name) => { - self.theme = theme_by_single_name(theme_name).unwrap_or(*THEME_DEFAULT); + self.theme = theme_by_short_name(theme_name).unwrap_or(*THEME_DEFAULT); } AssetsOp::Layout(layout) => { self.layout = layout; @@ -199,7 +200,8 @@ impl Context { match id { Some(id) => id, None => { - let prefix = util::single_type_name::() + let prefix = TypeInfo::ShortName + .of::() .trim() .replace(' ', "_") .to_lowercase(); diff --git a/src/core/component/definition.rs b/src/core/component/definition.rs index 6bf15cc1..e7452899 100644 --- a/src/core/component/definition.rs +++ b/src/core/component/definition.rs @@ -2,7 +2,8 @@ use crate::base::action; use crate::core::component::Context; use crate::core::AnyBase; use crate::html::{html, Markup, PrepareMarkup}; -use crate::{util, Weight}; +use crate::util::TypeInfo; +use crate::Weight; pub trait ComponentBase { fn render(&mut self, cx: &mut Context) -> Markup; @@ -13,8 +14,8 @@ pub trait ComponentTrait: AnyBase + ComponentBase + Send + Sync { where Self: Sized; - fn name(&self) -> String { - util::single_type_name::().to_owned() + fn name(&self) -> &'static str { + TypeInfo::ShortName.of::() } fn description(&self) -> Option { diff --git a/src/core/package/definition.rs b/src/core/package/definition.rs index 0d02b2a7..bf3deab8 100644 --- a/src/core/package/definition.rs +++ b/src/core/package/definition.rs @@ -12,7 +12,7 @@ pub type PackageRef = &'static dyn PackageTrait; /// Los paquetes deben implementar este *trait*. pub trait PackageTrait: AnyBase + Send + Sync { fn name(&self) -> L10n { - L10n::n(self.single_name()) + L10n::n(self.short_name()) } fn description(&self) -> L10n { diff --git a/src/core/theme/all.rs b/src/core/theme/all.rs index 51e9a556..d0fede7f 100644 --- a/src/core/theme/all.rs +++ b/src/core/theme/all.rs @@ -11,20 +11,20 @@ pub static THEMES: LazyStatic>> = LazyStatic::new(|| RwLock // DEFAULT THEME *********************************************************************************** pub static THEME_DEFAULT: LazyStatic = - LazyStatic::new(|| match theme_by_single_name(&config::SETTINGS.app.theme) { + LazyStatic::new(|| match theme_by_short_name(&config::SETTINGS.app.theme) { Some(theme) => theme, None => &crate::base::theme::Inception, }); // THEME BY NAME *********************************************************************************** -pub fn theme_by_single_name(single_name: &str) -> Option { - let single_name = single_name.to_lowercase(); +pub fn theme_by_short_name(short_name: &str) -> Option { + let short_name = short_name.to_lowercase(); match THEMES .read() .unwrap() .iter() - .find(|t| t.single_name().to_lowercase() == single_name) + .find(|t| t.short_name().to_lowercase() == short_name) { Some(theme) => Some(*theme), _ => None, diff --git a/src/db.rs b/src/db.rs index 58730818..dd657b54 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,5 +1,6 @@ //! Database access. +use crate::util::TypeInfo; use crate::{config, trace, LazyStatic}; pub use url::Url as DbUri; @@ -148,21 +149,14 @@ pub async fn exec_raw(stmt: String) -> Result { mod migration; pub use migration::prelude::*; -pub type MigrationItem = Box; - -#[macro_export] -macro_rules! new_migration { - ( $migration:ident ) => { - pub struct $migration; - - impl MigrationName for $migration { - fn name(&self) -> &str { - $crate::util::partial_type_name(module_path!(), 1) - } - } - }; +impl MigrationName for M { + fn name(&self) -> &str { + TypeInfo::NameTo(-2).of::() + } } +pub type MigrationItem = Box; + #[macro_export] macro_rules! migrations { () => { diff --git a/src/prelude.rs b/src/prelude.rs index 7ad1ab5a..80e9e5a8 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -37,7 +37,7 @@ pub use crate::locale::*; pub use crate::datetime::*; #[cfg(feature = "database")] -pub use crate::{db, db::*, migrations, new_migration}; +pub use crate::{db, db::*, migrations}; pub use crate::service; pub use crate::service::{HttpMessage, HttpRequest}; diff --git a/src/util.rs b/src/util.rs index a8438399..12a0cb37 100644 --- a/src/util.rs +++ b/src/util.rs @@ -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(&self) -> &'static str { + let type_name = std::any::type_name::(); + 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) -> &'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() -> &'static str { - partial_type_name(std::any::type_name::(), 1) -} - pub fn absolute_dir( root_path: impl Into, relative_path: impl Into,