Añade extensiones en módulos para añadir funciones

This commit is contained in:
Manuel Cillero 2022-05-02 20:00:22 +02:00
parent 8f429401eb
commit 9eede3321a
7 changed files with 96 additions and 26 deletions

View file

@ -1,14 +1,20 @@
use crate::{Lazy, app, run_now, trace};
use crate::db::*;
use super::ModuleTrait;
use super::{ExtensionTrait, ModuleTrait};
use std::sync::RwLock;
use std::sync::{Arc, RwLock};
use std::collections::HashMap;
// Módulos registrados.
static MODULES: Lazy<RwLock<Vec<&dyn ModuleTrait>>> = Lazy::new(|| {
RwLock::new(Vec::new())
});
// Extensiones registradas.
static EXTENSIONS: Lazy<RwLock<HashMap<&str, Arc<Vec<&dyn ExtensionTrait>>>>> = Lazy::new(|| {
RwLock::new(HashMap::new())
});
pub fn register_module(module: &'static dyn ModuleTrait) {
let mut list: Vec<&dyn ModuleTrait> = Vec::new();
add_to(&mut list, module);
@ -17,11 +23,24 @@ pub fn register_module(module: &'static dyn ModuleTrait) {
}
fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) {
if !MODULES.read().unwrap().iter().any(|m| m.name() == module.name()) {
if !list.iter().any(|m| m.name() == module.name()) {
if !MODULES.read().unwrap().iter().any(|m| m.type_name() == module.type_name()) {
if !list.iter().any(|m| m.type_name() == module.type_name()) {
trace::debug!("Registering \"{}\" module", module.single_name());
list.push(module);
let mut hmap = EXTENSIONS.write().unwrap();
for e in module.extensions().iter() {
if let Some(extensions) = hmap.get_mut(e.type_name()) {
let v = Arc::get_mut(extensions).unwrap();
v.push(*e);
v.sort_by_key(|e| e.weight());
} else {
hmap.insert(e.type_name(), Arc::new(vec![*e]));
}
}
let mut dependencies = module.dependencies();
dependencies.reverse();
for d in dependencies.iter() {
@ -37,6 +56,13 @@ pub fn modules(cfg: &mut app::web::ServiceConfig) {
}
}
pub fn extensions(type_name: &'static str) -> Option<Arc<Vec<&dyn ExtensionTrait>>> {
match EXTENSIONS.read().unwrap().get(type_name) {
Some(extensions) => Some(extensions.clone()),
_ => None,
}
}
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
pub fn migrations() {
run_now({

View file

@ -1,15 +1,16 @@
use crate::app;
use crate::util::partial_type_name;
use crate::{app, util};
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
use crate::db;
use super::ExtensionTrait;
pub trait BaseModule {
fn type_name(&self) -> &'static str;
fn single_name(&self) -> &'static str;
fn qualified_name(&self, last: usize) -> &'static str;
fn qualified_name(&self, last: u8) -> &'static str;
}
/// Los módulos deben implementar este *trait*.
@ -22,19 +23,23 @@ pub trait ModuleTrait: BaseModule + Send + Sync {
None
}
fn dependencies(&self) -> Vec<&'static dyn ModuleTrait> {
vec![]
}
#[allow(unused_variables)]
fn configure_module(&self, cfg: &mut app::web::ServiceConfig) {
}
fn extensions(&self) -> Vec<&'static dyn ExtensionTrait> {
vec![]
}
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
#[allow(unused_variables)]
fn migrations(&self) -> Vec<Box<dyn db::MigrationTrait>> {
vec![]
}
fn dependencies(&self) -> Vec<&'static dyn ModuleTrait> {
vec![]
}
}
impl<M: ?Sized + ModuleTrait> BaseModule for M {
@ -43,10 +48,10 @@ impl<M: ?Sized + ModuleTrait> BaseModule for M {
}
fn single_name(&self) -> &'static str {
partial_type_name(std::any::type_name::<Self>(), 1)
util::partial_type_name(std::any::type_name::<Self>(), 1)
}
fn qualified_name(&self, last: usize) -> &'static str {
partial_type_name(std::any::type_name::<Self>(), last)
fn qualified_name(&self, last: u8) -> &'static str {
util::partial_type_name(std::any::type_name::<Self>(), last)
}
}

View file

@ -0,0 +1,30 @@
use crate::util;
pub trait BaseExtension {
fn type_name(&self) -> &'static str;
fn single_name(&self) -> &'static str;
fn qualified_name(&self, last: u8) -> &'static str;
}
/// Las extensiones deben extender este *trait*.
pub trait ExtensionTrait: BaseExtension + Send + Sync {
fn weight(&self) -> i8 {
0
}
}
impl<E: ?Sized + ExtensionTrait> BaseExtension for E {
fn type_name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn single_name(&self) -> &'static str {
util::partial_type_name(std::any::type_name::<Self>(), 1)
}
fn qualified_name(&self, last: u8) -> &'static str {
util::partial_type_name(std::any::type_name::<Self>(), last)
}
}

View file

@ -3,6 +3,14 @@ pub use definition::{
BaseModule,
ModuleTrait,
};
mod extension;
pub use extension::{
BaseExtension,
ExtensionTrait,
};
pub(crate) mod all;
pub use all::register_module;
pub use all::{
extensions,
register_module
};

View file

@ -1,6 +1,6 @@
use crate::html::{Markup, html};
use crate::core::response::page::PageAssets;
use crate::util::partial_type_name;
use crate::util;
pub use std::any::Any as AnyComponent;
@ -9,7 +9,7 @@ pub trait BaseComponent {
fn single_name(&self) -> &'static str;
fn qualified_name(&self, last: usize) -> &'static str;
fn qualified_name(&self, last: u8) -> &'static str;
}
pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync {
@ -52,11 +52,11 @@ impl<C: ?Sized + ComponentTrait> BaseComponent for C {
}
fn single_name(&self) -> &'static str {
partial_type_name(std::any::type_name::<Self>(), 1)
util::partial_type_name(std::any::type_name::<Self>(), 1)
}
fn qualified_name(&self, last: usize) -> &'static str {
partial_type_name(std::any::type_name::<Self>(), last)
fn qualified_name(&self, last: u8) -> &'static str {
util::partial_type_name(std::any::type_name::<Self>(), last)
}
}

View file

@ -3,14 +3,14 @@ use crate::config::SETTINGS;
use crate::html::{Markup, html};
use crate::core::response::page::{ComponentTrait, Favicon, Page, PageAssets};
use crate::base::component::Chunck;
use crate::util::partial_type_name;
use crate::util;
pub trait BaseTheme {
fn type_name(&self) -> &'static str;
fn single_name(&self) -> &'static str;
fn qualified_name(&self, last: usize) -> &'static str;
fn qualified_name(&self, last: u8) -> &'static str;
}
/// Los temas deben implementar este "trait".
@ -143,10 +143,10 @@ impl<T: ?Sized + ThemeTrait> BaseTheme for T {
}
fn single_name(&self) -> &'static str {
partial_type_name(std::any::type_name::<Self>(), 1)
util::partial_type_name(std::any::type_name::<Self>(), 1)
}
fn qualified_name(&self, last: usize) -> &'static str {
partial_type_name(std::any::type_name::<Self>(), last)
fn qualified_name(&self, last: u8) -> &'static str {
util::partial_type_name(std::any::type_name::<Self>(), last)
}
}

View file

@ -47,11 +47,12 @@ macro_rules! theme_static_files {
}};
}
pub(crate) fn partial_type_name(type_name: &'static str, last: usize) -> &'static str {
pub(crate) fn partial_type_name(type_name: &'static str, last: u8) -> &'static str {
if last == 0 {
return type_name;
}
let positions: Vec<_> = type_name.rmatch_indices("::").collect();
let last: usize = last as usize;
if positions.len() < last {
return type_name;
}