Initial commit
This commit is contained in:
99
src/utils.rs
Normal file
99
src/utils.rs
Normal file
@@ -0,0 +1,99 @@
|
||||
use std::sync::{Condvar, Mutex};
|
||||
|
||||
pub fn normalize_title(input: &str) -> String {
|
||||
let mut out = String::with_capacity(input.len());
|
||||
for ch in input.chars() {
|
||||
if ch.is_ascii_alphanumeric() {
|
||||
out.push(ch.to_ascii_lowercase());
|
||||
} else if ch.is_whitespace() {
|
||||
out.push(' ');
|
||||
} else {
|
||||
out.push(' ');
|
||||
}
|
||||
}
|
||||
collapse_whitespace(&out)
|
||||
}
|
||||
|
||||
pub fn sanitize_filename(input: &str) -> String {
|
||||
let mut out = String::with_capacity(input.len());
|
||||
for ch in input.chars() {
|
||||
if matches!(ch, '<' | '>' | ':' | '"' | '/' | '\\' | '|' | '?' | '*') {
|
||||
out.push(' ');
|
||||
} else {
|
||||
out.push(ch);
|
||||
}
|
||||
}
|
||||
collapse_whitespace(&out)
|
||||
}
|
||||
|
||||
pub fn collapse_whitespace(input: &str) -> String {
|
||||
let mut out = String::with_capacity(input.len());
|
||||
let mut last_space = false;
|
||||
for ch in input.chars() {
|
||||
if ch.is_whitespace() {
|
||||
if !last_space {
|
||||
out.push(' ');
|
||||
last_space = true;
|
||||
}
|
||||
} else {
|
||||
last_space = false;
|
||||
out.push(ch);
|
||||
}
|
||||
}
|
||||
out.trim().to_string()
|
||||
}
|
||||
|
||||
pub struct Semaphore {
|
||||
state: Mutex<usize>,
|
||||
cvar: Condvar,
|
||||
}
|
||||
|
||||
impl Semaphore {
|
||||
pub fn new(count: usize) -> Self {
|
||||
Self {
|
||||
state: Mutex::new(count),
|
||||
cvar: Condvar::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn acquire(&self) -> SemaphoreGuard<'_> {
|
||||
let mut count = self.state.lock().unwrap();
|
||||
while *count == 0 {
|
||||
count = self.cvar.wait(count).unwrap();
|
||||
}
|
||||
*count -= 1;
|
||||
SemaphoreGuard { sem: self }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SemaphoreGuard<'a> {
|
||||
sem: &'a Semaphore,
|
||||
}
|
||||
|
||||
impl Drop for SemaphoreGuard<'_> {
|
||||
fn drop(&mut self) {
|
||||
let mut count = self.sem.state.lock().unwrap();
|
||||
*count += 1;
|
||||
self.sem.cvar.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{collapse_whitespace, normalize_title, sanitize_filename};
|
||||
|
||||
#[test]
|
||||
fn normalizes_title() {
|
||||
assert_eq!(normalize_title("The.Matrix!!"), "the matrix");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanitizes_filename() {
|
||||
assert_eq!(sanitize_filename("Bad:Name/Here"), "Bad Name Here");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collapses_whitespace() {
|
||||
assert_eq!(collapse_whitespace("a b c"), "a b c");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user