1#[inline]
6pub fn join_paths(prefix: &str, suffix: &str) -> &'static str {
7 let prefix = prefix.trim_end_matches('/');
8 let suffix = if suffix.starts_with('/') {
9 suffix
10 } else {
11 let owned = format!("/{suffix}");
13 return Box::leak(owned.into_boxed_str());
14 };
15
16 if suffix == "/" || suffix.is_empty() {
17 let path = if prefix.is_empty() { "/" } else { prefix };
18 return Box::leak(format!("{path}/").into_boxed_str());
19 }
20
21 let combined = if prefix.is_empty() {
22 suffix.to_string()
23 } else {
24 format!("{prefix}{suffix}")
25 };
26 Box::leak(combined.into_boxed_str())
27}
28
29#[macro_export]
31macro_rules! static_path {
32 ($prefix:literal, $suffix:literal) => {{
33 const PATH: &str = concat!($prefix, $suffix);
34 PATH
35 }};
36}
37
38#[cfg(test)]
39mod tests {
40 use super::join_paths;
41
42 #[test]
43 fn joins_prefix_and_suffix() {
44 let path = join_paths("/api", "/users");
45 assert_eq!(path, "/api/users");
46 }
47
48 #[test]
49 fn trims_trailing_slash_on_prefix_when_suffix_is_absolute() {
50 let path = join_paths("/api/", "/health");
51 assert_eq!(path, "/api/health");
52 }
53
54 #[test]
55 fn root_suffix_on_prefix() {
56 let path = join_paths("/ping", "/");
57 assert_eq!(path, "/ping/");
58 }
59
60 #[test]
61 fn empty_prefix_uses_suffix() {
62 let path = join_paths("", "/only");
63 assert_eq!(path, "/only");
64 }
65}