use std::{any::type_name, marker::PhantomData, sync::Arc};
pub fn get_table_name<T>() -> String {
let full_name = type_name::<T>();
let type_name = full_name.rsplit("::").next().unwrap_or(full_name);
let mut result = String::with_capacity(64);
let mut chars = type_name.chars().peekable();
let mut prev_is_lower_or_digit = false;
while let Some(ch) = chars.next() {
if ch.is_uppercase() {
if prev_is_lower_or_digit {
result.push('_');
}
result.push(ch.to_ascii_lowercase());
prev_is_lower_or_digit = true;
} else if ch.is_lowercase() || ch.is_digit(10) {
result.push(ch);
prev_is_lower_or_digit = true;
} else {
break;
}
}
result
}
pub struct QueryCondition<'a, Q, F>
where
F: Fn(&mut Q) + Send + Sync + 'a,
{
condition: Arc<F>,
_marker: PhantomData<&'a Q>,
}
impl<'a, Q, F> QueryCondition<'a, Q, F>
where
F: Fn(&mut Q) + Send + Sync + 'a,
{
pub fn new(query_fn: F) -> Self {
QueryCondition {
condition: Arc::new(query_fn),
_marker: PhantomData,
}
}
pub fn get(&self) -> impl Fn(&mut Q) + Send + Sync + 'a {
let arc_condition = self.condition.clone();
move |q| arc_condition(q)
}
}
#[cfg(test)]
mod tests {
use super::*;
struct ArticleTag { _tag: String }
#[test]
fn test_get_type_name() {
assert_eq!(get_table_name::<ArticleTag>(), "article_tag");
}
}