Skip to main content

cloudreve_api/api/v4/
uri.rs

1//! URI handling utilities for Cloudreve v4 API
2//!
3//! This module provides utilities for converting file paths to the Cloudreve URI format
4//! and validating URIs according to the Cloudreve API specification.
5
6/// Cloudreve URI prefix for user files
7pub const CLOUDREVE_URI_PREFIX: &str = "cloudreve://my/";
8
9/// Converts a file path to Cloudreve URI format
10///
11/// # Arguments
12/// * `path` - File path (can be absolute, relative, or already a URI)
13///
14/// # Returns
15/// A properly formatted Cloudreve URI string
16///
17/// # Examples
18/// ```
19/// use cloudreve_api::api::v4::uri::path_to_uri;
20///
21/// assert_eq!(path_to_uri("/path/to/file.txt"), "cloudreve://my/path/to/file.txt");
22/// assert_eq!(path_to_uri("path/to/file.txt"), "cloudreve://my/path/to/file.txt");
23/// assert_eq!(path_to_uri("cloudreve://my/path/to/file.txt"), "cloudreve://my/path/to/file.txt");
24/// ```
25pub fn path_to_uri(path: &str) -> String {
26    // If already a valid Cloudreve URI, return as-is
27    if path.starts_with("cloudreve://") {
28        return path.to_string();
29    }
30
31    // Remove leading slash if present
32    let trimmed_path = path.strip_prefix('/').unwrap_or(path);
33
34    // Build URI
35    format!("{}{}", CLOUDREVE_URI_PREFIX, trimmed_path)
36}
37
38/// Validates if a string is a properly formatted Cloudreve URI
39///
40/// # Arguments
41/// * `uri` - URI string to validate
42///
43/// # Returns
44/// `true` if the URI is valid, `false` otherwise
45pub fn is_valid_uri(uri: &str) -> bool {
46    uri.starts_with(CLOUDREVE_URI_PREFIX) && uri.len() >= CLOUDREVE_URI_PREFIX.len()
47}
48
49/// Extracts the path component from a Cloudreve URI
50///
51/// # Arguments
52/// * `uri` - Cloudreve URI string
53///
54/// # Returns
55/// The path component, or an error if the URI is invalid
56pub fn uri_to_path(uri: &str) -> Result<&str, String> {
57    if !uri.starts_with(CLOUDREVE_URI_PREFIX) {
58        return Err(format!(
59            "Invalid Cloudreve URI: expected format 'cloudreve://my/...', got: {}",
60            uri
61        ));
62    }
63
64    let path = &uri[CLOUDREVE_URI_PREFIX.len() - 1..];
65    Ok(path)
66}
67
68/// Converts multiple paths to URIs
69///
70/// # Arguments
71/// * `paths` - Slice of path strings
72///
73/// # Returns
74/// Vector of converted URIs
75pub fn paths_to_uris(paths: &[&str]) -> Vec<String> {
76    paths.iter().map(|p| path_to_uri(p)).collect()
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    #[test]
84    fn test_path_to_uri_absolute() {
85        assert_eq!(
86            path_to_uri("/path/to/file.txt"),
87            "cloudreve://my/path/to/file.txt"
88        );
89    }
90
91    #[test]
92    fn test_path_to_uri_relative() {
93        assert_eq!(
94            path_to_uri("path/to/file.txt"),
95            "cloudreve://my/path/to/file.txt"
96        );
97    }
98
99    #[test]
100    fn test_path_to_uri_already_uri() {
101        assert_eq!(
102            path_to_uri("cloudreve://my/path/to/file.txt"),
103            "cloudreve://my/path/to/file.txt"
104        );
105    }
106
107    #[test]
108    fn test_path_to_uri_root() {
109        assert_eq!(path_to_uri("/"), "cloudreve://my/");
110    }
111
112    #[test]
113    fn test_is_valid_uri() {
114        assert!(is_valid_uri("cloudreve://my/path/to/file.txt"));
115        assert!(is_valid_uri("cloudreve://my/"));
116        assert!(!is_valid_uri("/path/to/file.txt"));
117        assert!(!is_valid_uri("path/to/file.txt"));
118        assert!(!is_valid_uri("cloudreve://"));
119    }
120
121    #[test]
122    fn test_uri_to_path() {
123        assert_eq!(
124            uri_to_path("cloudreve://my/path/to/file.txt").unwrap(),
125            "/path/to/file.txt"
126        );
127        assert_eq!(uri_to_path("cloudreve://my/").unwrap(), "/");
128    }
129
130    #[test]
131    fn test_uri_to_path_invalid() {
132        assert!(uri_to_path("/path/to/file.txt").is_err());
133        assert!(uri_to_path("cloudreve://").is_err());
134    }
135
136    #[test]
137    fn test_paths_to_uris() {
138        let paths = vec!["/file1.txt", "file2.txt", "cloudreve://my/file3.txt"];
139        let uris = paths_to_uris(&paths);
140        assert_eq!(
141            uris,
142            vec![
143                "cloudreve://my/file1.txt",
144                "cloudreve://my/file2.txt",
145                "cloudreve://my/file3.txt"
146            ]
147        );
148    }
149}