Añade función para crear handler único al compilar

Permite asignar automáticamente el "handler" a componentes, módulos,
temas y acciones.
This commit is contained in:
Manuel Cillero 2022-07-26 20:57:32 +02:00
parent 53668b8719
commit b986bfcd13
33 changed files with 156 additions and 111 deletions

View file

@ -1,6 +1,6 @@
use pagetop::prelude::*;
pub const MODULE_ADMIN: &str = "pagetop-admin::module::admin";
pub_const_handler!(MODULE_ADMIN);
localize!("src/locales");
@ -9,7 +9,7 @@ mod summary;
pub struct Admin;
impl ModuleTrait for Admin {
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
MODULE_ADMIN
}

View file

@ -1,6 +1,6 @@
use pagetop::prelude::*;
pub const MODULE_NODE: &str = "pagetop-node::module::node";
pub_const_handler!(MODULE_NODE);
localize!("src/locales");
@ -10,7 +10,7 @@ mod migration;
pub struct Node;
impl ModuleTrait for Node {
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
MODULE_NODE
}

View file

@ -1,6 +1,6 @@
use pagetop::prelude::*;
pub const MODULE_USER: &str = "pagetop-user::module::user";
pub_const_handler!(MODULE_USER);
localize!("src/locales");
@ -9,7 +9,7 @@ mod migration;
pub struct User;
impl ModuleTrait for User {
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
MODULE_USER
}

View file

@ -1,6 +1,6 @@
use crate::prelude::*;
pub const COMPONENT_ANCHOR: &str = "pagetop::component::anchor";
pub_const_handler!(COMPONENT_ANCHOR);
pub enum AnchorType {
Button,
@ -49,7 +49,7 @@ impl ComponentTrait for Anchor {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_ANCHOR
}

View file

@ -1,11 +1,8 @@
use crate::prelude::*;
pub const COMPONENT_BLOCK: &str = "pagetop::component::block";
pub_const_handler!(COMPONENT_BLOCK);
hook_before_render_component!(
HOOK_BEFORE_RENDER_BLOCK = "pagetop::action::before_render_block",
Block
);
hook_before_render_component!(HOOK_BEFORE_RENDER_BLOCK, Block);
pub struct Block {
weight : isize,
@ -30,7 +27,7 @@ impl ComponentTrait for Block {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_BLOCK
}

View file

@ -1,11 +1,8 @@
use crate::prelude::*;
pub const COMPONENT_CONTAINER: &str = "pagetop::component::container";
pub_const_handler!(COMPONENT_CONTAINER);
hook_before_render_component!(
HOOK_BEFORE_RENDER_CONTAINER = "pagetop::action::before_render_container",
Container
);
hook_before_render_component!(HOOK_BEFORE_RENDER_CONTAINER, Container);
pub enum ContainerType {
Header,
@ -40,7 +37,7 @@ impl ComponentTrait for Container {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_CONTAINER
}

View file

@ -1,6 +1,6 @@
use crate::prelude::*;
pub const COMPONENT_BUTTON: &str = "pagetop::component::form::button";
pub_const_handler!(COMPONENT_BUTTON);
pub enum ButtonType {
Button,
@ -36,7 +36,7 @@ impl ComponentTrait for Button {
.with_classes(ClassesOp::AddFirst, "form-button")
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_BUTTON
}

View file

@ -1,6 +1,6 @@
use crate::prelude::*;
pub const COMPONENT_DATE: &str = "pagetop::component::form::date";
pub_const_handler!(COMPONENT_DATE);
pub struct Date {
weight : isize,
@ -40,7 +40,7 @@ impl ComponentTrait for Date {
.with_classes(ClassesOp::AddFirst, "form-type-date")
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_DATE
}

View file

@ -1,11 +1,8 @@
use crate::prelude::*;
pub const COMPONENT_FORM: &str = "pagetop::component::form";
pub_const_handler!(COMPONENT_FORM);
hook_before_render_component!(
HOOK_BEFORE_RENDER_FORM = "pagetop::action::before_render_form",
Form
);
hook_before_render_component!(HOOK_BEFORE_RENDER_FORM, Form);
pub enum FormMethod {
Get,
@ -39,7 +36,7 @@ impl ComponentTrait for Form {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_FORM
}

View file

@ -1,6 +1,6 @@
use crate::prelude::*;
pub const COMPONENT_HIDDEN: &str = "pagetop::component::form::hidden";
pub_const_handler!(COMPONENT_HIDDEN);
pub struct Hidden {
weight: isize,
@ -17,7 +17,7 @@ impl ComponentTrait for Hidden {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_HIDDEN
}

View file

@ -1,6 +1,6 @@
use crate::prelude::*;
pub const COMPONENT_INPUT: &str = "pagetop::component::form::input";
pub_const_handler!(COMPONENT_INPUT);
pub enum InputType {
Email,
@ -57,7 +57,7 @@ impl ComponentTrait for Input {
.with_classes(ClassesOp::AddFirst, "form-type-textfield")
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_INPUT
}

View file

@ -1,11 +1,8 @@
use crate::prelude::*;
pub const COMPONENT_COLUMN: &str = "pagetop::component::grid::column";
pub_const_handler!(COMPONENT_COLUMN);
hook_before_render_component!(
HOOK_BEFORE_RENDER_COLUMN = "pagetop::action::before_render_column",
Column
);
hook_before_render_component!(HOOK_BEFORE_RENDER_COLUMN, Column);
const SIZE_DEFAULT: &str = "col-md";
const SIZE_1_OF_12: &str = "col-md-1";
@ -59,7 +56,7 @@ impl ComponentTrait for Column {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_COLUMN
}

View file

@ -1,11 +1,8 @@
use crate::prelude::*;
pub const COMPONENT_ROW: &str = "pagetop::component::grid::row";
pub_const_handler!(COMPONENT_ROW);
hook_before_render_component!(
HOOK_BEFORE_RENDER_ROW = "pagetop::action::before_render_row",
Row
);
hook_before_render_component!(HOOK_BEFORE_RENDER_ROW, Row);
pub struct Row {
weight : isize,
@ -28,7 +25,7 @@ impl ComponentTrait for Row {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_ROW
}

View file

@ -1,6 +1,6 @@
use crate::prelude::*;
pub const COMPONENT_HEADING: &str = "pagetop::component::heading";
pub_const_handler!(COMPONENT_HEADING);
pub enum HeadingType {
H1,
@ -46,7 +46,7 @@ impl ComponentTrait for Heading {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_HEADING
}

View file

@ -1,6 +1,6 @@
use crate::prelude::*;
pub const COMPONENT_HTML: &str = "pagetop::component::html";
pub_const_handler!(COMPONENT_HTML);
pub struct Html {
weight : isize,
@ -19,7 +19,7 @@ impl ComponentTrait for Html {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_HTML
}

View file

@ -1,6 +1,6 @@
use crate::prelude::*;
pub const COMPONENT_ICON: &str = "pagetop::component::icon";
pub_const_handler!(COMPONENT_ICON);
pub struct Icon {
weight : isize,
@ -19,7 +19,7 @@ impl ComponentTrait for Icon {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_ICON
}

View file

@ -1,6 +1,6 @@
use crate::prelude::*;
pub const COMPONENT_IMAGE: &str = "pagetop::component::image";
pub_const_handler!(COMPONENT_IMAGE);
pub struct Image {
weight : isize,
@ -23,7 +23,7 @@ impl ComponentTrait for Image {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_IMAGE
}

View file

@ -1,6 +1,6 @@
use crate::prelude::*;
pub const COMPONENT_MENUITEM: &str = "pagetop::component::menu_item";
pub_const_handler!(COMPONENT_MENUITEM);
pub enum MenuItemType {
Label(String),
@ -29,7 +29,7 @@ impl ComponentTrait for MenuItem {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_MENUITEM
}
@ -163,12 +163,9 @@ impl MenuItem {
// Menu.
pub const COMPONENT_MENU: &str = "pagetop::component::menu";
pub_const_handler!(COMPONENT_MENU);
hook_before_render_component!(
HOOK_BEFORE_RENDER_MENU = "pagetop::action::before_render_menu",
Menu
);
hook_before_render_component!(HOOK_BEFORE_RENDER_MENU, Menu);
pub struct Menu {
weight : isize,
@ -191,7 +188,7 @@ impl ComponentTrait for Menu {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_MENU
}

View file

@ -1,6 +1,6 @@
use crate::prelude::*;
pub const COMPONENT_PARAGRAPH: &str = "pagetop::component::paragraph";
pub_const_handler!(COMPONENT_PARAGRAPH);
pub enum ParagraphDisplay {
XxLarge,
@ -34,7 +34,7 @@ impl ComponentTrait for Paragraph {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
COMPONENT_PARAGRAPH
}

View file

@ -1,13 +1,13 @@
use crate::prelude::*;
pub const MODULE_DEFAULT_HOMEPAGE: &str = "pagetop::module::homepage::default";
pub_const_handler!(MODULE_DEFAULT_HOMEPAGE);
localize!("src/base/module/homepage/locales");
pub struct DefaultHomePage;
impl ModuleTrait for DefaultHomePage {
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
MODULE_DEFAULT_HOMEPAGE
}

View file

@ -1,13 +1,13 @@
use crate::prelude::*;
pub const THEME_ALINER: &str = "pagetop::theme::aliner";
pub_const_handler!(THEME_ALINER);
include!(concat!(env!("OUT_DIR"), "/aliner.rs"));
pub struct Aliner;
impl ThemeTrait for Aliner {
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
THEME_ALINER
}

View file

@ -1,6 +1,6 @@
use crate::prelude::*;
pub const THEME_BOOTSIER: &str = "pagetop::theme::bootsier";
pub_const_handler!(THEME_BOOTSIER);
include!(concat!(env!("OUT_DIR"), "/bootsier.rs"));
@ -9,7 +9,7 @@ localize!("src/base/theme/bootsier/locales");
pub struct Bootsier;
impl ThemeTrait for Bootsier {
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
THEME_BOOTSIER
}

View file

@ -1,13 +1,13 @@
use crate::prelude::*;
pub const THEME_BULMIX: &str = "pagetop::theme::bulmix";
pub_const_handler!(THEME_BULMIX);
include!(concat!(env!("OUT_DIR"), "/bulmix.rs"));
pub struct Bulmix;
impl ThemeTrait for Bulmix {
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
THEME_BULMIX
}

View file

@ -1,11 +1,11 @@
use crate::prelude::*;
pub const THEME_MINIMAL: &str = "pagetop::theme::minimal";
pub_const_handler!(THEME_MINIMAL);
pub struct Minimal;
impl ThemeTrait for Minimal {
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
THEME_MINIMAL
}
}

View file

@ -1,6 +1,6 @@
use super::InContext;
use crate::html::{html, Markup};
use crate::util;
use crate::util::{single_type_name, Handler};
pub use std::any::Any as AnyComponent;
@ -13,10 +13,10 @@ pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync {
where
Self: Sized;
fn handler(&self) -> &'static str;
fn handler(&self) -> Handler;
fn name(&self) -> String {
util::single_type_name::<Self>().to_owned()
single_type_name::<Self>().to_owned()
}
fn description(&self) -> Option<String> {
@ -73,9 +73,9 @@ pub fn component_mut<C: 'static>(component: &mut dyn ComponentTrait) -> &mut C {
#[macro_export]
macro_rules! hook_before_render_component {
( $ACTION_HANDLER:ident = $handler:literal, $Component:ty ) => {
( $ACTION_HANDLER:ident, $Component:ty ) => {
paste::paste! {
const $ACTION_HANDLER: &str = $handler;
$crate::pub_const_handler!($ACTION_HANDLER);
type Action = fn(&$Component, &mut InContext);
@ -92,7 +92,7 @@ macro_rules! hook_before_render_component {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
$ACTION_HANDLER
}

View file

@ -1,29 +1,30 @@
use super::{HookAction, ActionsHolder};
use crate::LazyStatic;
use crate::util::Handler;
use std::collections::HashMap;
use std::sync::RwLock;
// Registered actions.
static ACTIONS: LazyStatic<RwLock<HashMap<&str, ActionsHolder>>> = LazyStatic::new(||
static ACTIONS: LazyStatic<RwLock<HashMap<Handler, ActionsHolder>>> = LazyStatic::new(||
RwLock::new(HashMap::new())
);
pub fn add_action(action: HookAction) {
let mut actions = ACTIONS.write().unwrap();
let action_handler = action.handler();
if let Some(holder) = actions.get_mut(action_handler) {
if let Some(holder) = actions.get_mut(&action_handler) {
holder.add(action);
} else {
actions.insert(action_handler, ActionsHolder::new_with(action));
}
}
pub fn run_actions<B, F>(action_handler: &str, f: F)
pub fn run_actions<B, F>(action_handler: Handler, f: F)
where
F: FnMut(&HookAction) -> B,
{
if let Some(holder) = ACTIONS.read().unwrap().get(action_handler) {
if let Some(holder) = ACTIONS.read().unwrap().get(&action_handler) {
holder.iter_map(f)
}
}

View file

@ -1,3 +1,5 @@
use crate::util::Handler;
pub use std::any::Any as AnyHookAction;
pub trait HookActionTrait: AnyHookAction + Send + Sync {
@ -5,7 +7,7 @@ pub trait HookActionTrait: AnyHookAction + Send + Sync {
where
Self: Sized;
fn handler(&self) -> &'static str;
fn handler(&self) -> Handler;
fn weight(&self) -> isize {
0

View file

@ -1,5 +1,6 @@
use crate::app;
use crate::core::hook::HookAction;
use crate::{app, util};
use crate::util::{single_type_name, Handler};
#[cfg(feature = "database")]
use crate::db::MigrationItem;
@ -10,7 +11,7 @@ pub trait BaseModule {
/// Los módulos deben implementar este *trait*.
pub trait ModuleTrait: BaseModule + Send + Sync {
fn handler(&self) -> &'static str;
fn handler(&self) -> Handler;
fn name(&self) -> String {
self.single_name().to_owned()
@ -40,6 +41,6 @@ pub trait ModuleTrait: BaseModule + Send + Sync {
impl<M: ?Sized + ModuleTrait> BaseModule for M {
fn single_name(&self) -> &'static str {
util::single_type_name::<Self>()
single_type_name::<Self>()
}
}

View file

@ -1,10 +1,11 @@
use crate::app;
use crate::base::component::{Container, Html};
use crate::concat_string;
use crate::config::SETTINGS;
use crate::core::component::{ComponentTrait, InContext, InContextOp};
use crate::html::{html, Favicon, Markup};
use crate::response::page::Page;
use crate::{concat_string, util};
use crate::util::{single_type_name, Handler};
pub trait BaseTheme {
fn single_name(&self) -> &'static str;
@ -12,7 +13,7 @@ pub trait BaseTheme {
/// Los temas deben implementar este "trait".
pub trait ThemeTrait: BaseTheme + Send + Sync {
fn handler(&self) -> &'static str;
fn handler(&self) -> Handler;
fn name(&self) -> String {
self.single_name().to_owned()
@ -144,6 +145,6 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
impl<T: ?Sized + ThemeTrait> BaseTheme for T {
fn single_name(&self) -> &'static str {
util::single_type_name::<Self>()
single_type_name::<Self>()
}
}

View file

@ -1,7 +1,15 @@
//! Re-exporta recursos comunes.
// Global macros and helpers.
pub use crate::{args, concat_string, theme_static_files, util, LazyStatic};
pub use crate::{
args,
concat_string,
pub_const_handler,
theme_static_files,
LazyStatic
};
pub use crate::util;
pub use crate::util::Handler;
pub use crate::config::SETTINGS;

View file

@ -1,7 +1,9 @@
use super::Page;
use crate::core::hook::{AnyHookAction, HookActionTrait};
use crate::pub_const_handler;
use crate::util::Handler;
pub const HOOK_BEFORE_RENDER_PAGE: &str = "pagetop::hook::before_render_page";
pub_const_handler!(HOOK_BEFORE_RENDER_PAGE);
type Hook = fn(&mut Page);
@ -18,7 +20,7 @@ impl HookActionTrait for BeforeRenderPageHook {
}
}
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
HOOK_BEFORE_RENDER_PAGE
}

View file

@ -1,3 +1,66 @@
pub type Handler = u64;
// https://stackoverflow.com/a/71464396
pub const fn handler(
module_path: &'static str,
file: &'static str,
line: u32,
column: u32,
) -> Handler {
let mut hash = 0xcbf29ce484222325;
let prime = 0x00000100000001B3;
let mut bytes = module_path.as_bytes();
let mut i = 0;
while i < bytes.len() {
hash ^= bytes[i] as u64;
hash = hash.wrapping_mul(prime);
i += 1;
}
bytes = file.as_bytes();
i = 0;
while i < bytes.len() {
hash ^= bytes[i] as u64;
hash = hash.wrapping_mul(prime);
i += 1;
}
hash ^= line as u64;
hash = hash.wrapping_mul(prime);
hash ^= column as u64;
hash = hash.wrapping_mul(prime);
hash
}
#[macro_export]
macro_rules! pub_const_handler {
( $HANDLER:ident ) => {
pub const $HANDLER: $crate::util::Handler = $crate::util::handler(
module_path!(),
file!(),
line!(),
column!(),
);
};
}
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)
}
#[macro_export]
/// Macro para construir grupos de pares clave-valor.
///
@ -34,18 +97,3 @@ macro_rules! theme_static_files {
}
}};
}
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)
}

View file

@ -11,12 +11,12 @@ static MDBOOK: LazyStatic<HashMap<&'static str, Resource>> = LazyStatic::new(||
generate()
);
pub const MODULE_MDBOOK: &str = "pagetop::website::module::mdbook";
pub_const_handler!(MODULE_MDBOOK);
pub struct MdBook;
impl ModuleTrait for MdBook {
fn handler(&self) -> &'static str {
fn handler(&self) -> Handler {
MODULE_MDBOOK
}