use std::{ffi::OsString, fs::DirEntry};
#[derive(Debug, Clone)]
pub struct RouteParams {
pub parent_route: String,
pub full_route: String,
pub file_name: String,
pub file_stem: String,
pub file_path: OsString,
pub is_protected: bool,
pub is_dir: bool,
}
impl RouteParams {
pub fn new(parent_route: &str, entry: &DirEntry, mut is_protected: bool) -> Self {
let parent_route = parent_route.to_string();
let file_name = entry.file_name().to_string_lossy().to_string();
let file_stem = file_name.split('.').next().unwrap_or("").to_string();
let is_dir = entry.file_type().unwrap().is_dir();
let full_route = if is_dir {
is_protected = is_protected || file_name.starts_with("$");
let end_point = file_name.replace("$", "");
format!("{}/{}", parent_route, end_point)
} else {
parent_route.clone()
};
let file_path = entry.path().into_os_string();
Self {
parent_route,
full_route,
file_name,
file_path,
file_stem,
is_protected,
is_dir,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs::{self, File};
use std::path::Path;
use tempfile::TempDir;
fn create_test_file(dir: &Path, filename: &str) -> DirEntry {
let file_path = dir.join(filename);
File::create(&file_path).unwrap();
let entries: Vec<DirEntry> = fs::read_dir(dir)
.unwrap()
.filter_map(|entry| entry.ok())
.filter(|entry| entry.file_name().to_string_lossy() == filename)
.collect();
entries.into_iter().next().unwrap()
}
fn create_test_dir(parent_dir: &Path, dirname: &str) -> DirEntry {
let dir_path = parent_dir.join(dirname);
fs::create_dir(&dir_path).unwrap();
let entries: Vec<DirEntry> = fs::read_dir(parent_dir)
.unwrap()
.filter_map(|entry| entry.ok())
.filter(|entry| entry.file_name().to_string_lossy() == dirname)
.collect();
entries.into_iter().next().unwrap()
}
#[test]
fn test_new_with_regular_file() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_file(temp_dir.path(), "get.json");
let params = RouteParams::new("/api/users", &entry, false);
assert_eq!(params.parent_route, "/api/users");
assert_eq!(params.full_route, "/api/users");
assert_eq!(params.file_name, "get.json");
assert_eq!(params.file_stem, "get");
assert!(!params.is_protected);
assert!(!params.is_dir);
}
#[test]
fn test_new_with_protected_file() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_file(temp_dir.path(), "$get.json");
let params = RouteParams::new("/api/users", &entry, false);
assert_eq!(params.parent_route, "/api/users");
assert_eq!(params.full_route, "/api/users");
assert_eq!(params.file_name, "$get.json");
assert_eq!(params.file_stem, "$get");
assert!(!params.is_protected); assert!(!params.is_dir);
}
#[test]
fn test_new_with_inherited_protection() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_file(temp_dir.path(), "get.json");
let params = RouteParams::new("/api/users", &entry, true);
assert_eq!(params.parent_route, "/api/users");
assert_eq!(params.full_route, "/api/users");
assert_eq!(params.file_name, "get.json");
assert_eq!(params.file_stem, "get");
assert!(params.is_protected); assert!(!params.is_dir);
}
#[test]
fn test_new_with_regular_directory() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_dir(temp_dir.path(), "products");
let params = RouteParams::new("/api", &entry, false);
assert_eq!(params.parent_route, "/api");
assert_eq!(params.full_route, "/api/products");
assert_eq!(params.file_name, "products");
assert_eq!(params.file_stem, "products");
assert!(!params.is_protected);
assert!(params.is_dir);
}
#[test]
fn test_new_with_protected_directory() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_dir(temp_dir.path(), "$admin");
let params = RouteParams::new("/api", &entry, false);
assert_eq!(params.parent_route, "/api");
assert_eq!(params.full_route, "/api/admin"); assert_eq!(params.file_name, "$admin");
assert_eq!(params.file_stem, "$admin");
assert!(params.is_protected);
assert!(params.is_dir);
}
#[test]
fn test_new_with_auth_file() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_file(temp_dir.path(), "{auth}.json");
let params = RouteParams::new("/api/auth", &entry, false);
assert_eq!(params.parent_route, "/api/auth");
assert_eq!(params.full_route, "/api/auth");
assert_eq!(params.file_name, "{auth}.json");
assert_eq!(params.file_stem, "{auth}");
assert!(!params.is_protected);
assert!(!params.is_dir);
}
#[test]
fn test_new_with_rest_file() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_file(temp_dir.path(), "rest{_id:int}.json");
let params = RouteParams::new("/api/products", &entry, false);
assert_eq!(params.parent_route, "/api/products");
assert_eq!(params.full_route, "/api/products");
assert_eq!(params.file_name, "rest{_id:int}.json");
assert_eq!(params.file_stem, "rest{_id:int}");
assert!(!params.is_protected);
assert!(!params.is_dir);
}
#[test]
fn test_new_with_upload_directory() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_dir(temp_dir.path(), "{upload}");
let params = RouteParams::new("/api", &entry, false);
assert_eq!(params.parent_route, "/api");
assert_eq!(params.full_route, "/api/{upload}");
assert_eq!(params.file_name, "{upload}");
assert_eq!(params.file_stem, "{upload}");
assert!(!params.is_protected);
assert!(params.is_dir);
}
#[test]
fn test_new_with_upload_temp_directory() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_dir(temp_dir.path(), "{upload}{temp}-docs");
let params = RouteParams::new("/api", &entry, false);
assert_eq!(params.parent_route, "/api");
assert_eq!(params.full_route, "/api/{upload}{temp}-docs");
assert_eq!(params.file_name, "{upload}{temp}-docs");
assert_eq!(params.file_stem, "{upload}{temp}-docs");
assert!(!params.is_protected);
assert!(params.is_dir);
}
#[test]
fn test_new_with_empty_parent_route() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_file(temp_dir.path(), "index.json");
let params = RouteParams::new("", &entry, false);
assert_eq!(params.parent_route, "");
assert_eq!(params.full_route, "");
assert_eq!(params.file_name, "index.json");
assert_eq!(params.file_stem, "index");
assert!(!params.is_protected);
assert!(!params.is_dir);
}
#[test]
fn test_new_with_root_directory() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_dir(temp_dir.path(), "api");
let params = RouteParams::new("", &entry, false);
assert_eq!(params.parent_route, "");
assert_eq!(params.full_route, "/api");
assert_eq!(params.file_name, "api");
assert_eq!(params.file_stem, "api");
assert!(!params.is_protected);
assert!(params.is_dir);
}
#[test]
fn test_new_with_complex_filename() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_file(temp_dir.path(), "get{id}.json");
let params = RouteParams::new("/api/users", &entry, false);
assert_eq!(params.parent_route, "/api/users");
assert_eq!(params.full_route, "/api/users");
assert_eq!(params.file_name, "get{id}.json");
assert_eq!(params.file_stem, "get{id}");
assert!(!params.is_protected);
assert!(!params.is_dir);
}
#[test]
fn test_new_with_range_filename() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_file(temp_dir.path(), "get{1-5}.json");
let params = RouteParams::new("/api/products", &entry, false);
assert_eq!(params.parent_route, "/api/products");
assert_eq!(params.full_route, "/api/products");
assert_eq!(params.file_name, "get{1-5}.json");
assert_eq!(params.file_stem, "get{1-5}");
assert!(!params.is_protected);
assert!(!params.is_dir);
}
#[test]
fn test_new_with_nested_protected_structure() {
let temp_dir = TempDir::new().unwrap();
let entry = create_test_dir(temp_dir.path(), "$admin");
let params = RouteParams::new("/api", &entry, true);
assert_eq!(params.parent_route, "/api");
assert_eq!(params.full_route, "/api/admin");
assert_eq!(params.file_name, "$admin");
assert_eq!(params.file_stem, "$admin");
assert!(params.is_protected); assert!(params.is_dir);
}
#[test]
fn test_file_stem_extraction() {
let temp_dir = TempDir::new().unwrap();
let test_cases = vec![
("test.json", "test"),
("test.txt", "test"),
("test.html", "test"),
("test", "test"),
("test.backup.json", "test"), ("{auth}.json", "{auth}"),
("$get.json", "$get"),
];
for (filename, expected_stem) in test_cases {
let entry = create_test_file(temp_dir.path(), filename);
let params = RouteParams::new("/test", &entry, false);
assert_eq!(params.file_stem, expected_stem, "Failed for filename: {}", filename);
}
}
}