refactor
This commit is contained in:
@@ -4,7 +4,9 @@ pub mod error;
|
||||
pub mod http;
|
||||
pub mod json;
|
||||
pub mod named_entity;
|
||||
pub mod setops;
|
||||
pub mod storage_paths;
|
||||
pub mod text;
|
||||
pub mod time;
|
||||
pub mod tracing;
|
||||
pub mod validation;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
use std::collections::HashSet;
|
||||
use std::hash::Hash;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::error::AppResult;
|
||||
use crate::state::PgPooledConnection;
|
||||
|
||||
/// Intersect an optional base set with a new set, returning the resulting option.
|
||||
pub fn intersect_option_sets<T>(base: Option<HashSet<T>>, next: HashSet<T>) -> Option<HashSet<T>>
|
||||
where
|
||||
T: Eq + Hash + Copy,
|
||||
{
|
||||
Some(match base {
|
||||
Some(existing) => existing.intersection(&next).copied().collect(),
|
||||
None => next,
|
||||
})
|
||||
}
|
||||
|
||||
/// Iteratively intersect documents linked via a join table loader.
|
||||
pub fn load_linked_doc_ids<F>(
|
||||
conn: &mut PgPooledConnection,
|
||||
ids: &[Uuid],
|
||||
mut loader: F,
|
||||
) -> AppResult<HashSet<Uuid>>
|
||||
where
|
||||
F: FnMut(&mut PgPooledConnection, Uuid) -> AppResult<HashSet<Uuid>>,
|
||||
{
|
||||
let mut current: Option<HashSet<Uuid>> = None;
|
||||
|
||||
for id in ids {
|
||||
let docs_set = loader(conn, *id)?;
|
||||
current = intersect_option_sets(current, docs_set);
|
||||
|
||||
if current.as_ref().is_some_and(|set| set.is_empty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(current.unwrap_or_default())
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
use crate::error::{AppError, AppResult};
|
||||
|
||||
/// Normalizes an identifier-like user input by trimming, enforcing length, and validating characters.
|
||||
pub fn normalize_identifier<F>(
|
||||
value: &str,
|
||||
max_len: usize,
|
||||
empty_message: &str,
|
||||
length_message: &str,
|
||||
invalid_message: Option<&str>,
|
||||
mut validator: F,
|
||||
) -> AppResult<String>
|
||||
where
|
||||
F: FnMut(char) -> bool,
|
||||
{
|
||||
let trimmed = value.trim();
|
||||
if trimmed.is_empty() {
|
||||
return Err(AppError::bad_request(empty_message));
|
||||
}
|
||||
|
||||
if trimmed.len() > max_len {
|
||||
return Err(AppError::bad_request(length_message));
|
||||
}
|
||||
|
||||
if let Some(msg) = invalid_message {
|
||||
if !trimmed.chars().all(|ch| validator(ch)) {
|
||||
return Err(AppError::bad_request(msg));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(trimmed.to_string())
|
||||
}
|
||||
Reference in New Issue
Block a user