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()..];
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!(path_to_uri("/path/to/file.txt"), "cloudreve://my/path/to/file.txt");
86    }
87
88    #[test]
89    fn test_path_to_uri_relative() {
90        assert_eq!(path_to_uri("path/to/file.txt"), "cloudreve://my/path/to/file.txt");
91    }
92
93    #[test]
94    fn test_path_to_uri_already_uri() {
95        assert_eq!(
96            path_to_uri("cloudreve://my/path/to/file.txt"),
97            "cloudreve://my/path/to/file.txt"
98        );
99    }
100
101    #[test]
102    fn test_path_to_uri_root() {
103        assert_eq!(path_to_uri("/"), "cloudreve://my/");
104    }
105
106    #[test]
107    fn test_is_valid_uri() {
108        assert!(is_valid_uri("cloudreve://my/path/to/file.txt"));
109        assert!(is_valid_uri("cloudreve://my/"));
110        assert!(!is_valid_uri("/path/to/file.txt"));
111        assert!(!is_valid_uri("path/to/file.txt"));
112        assert!(!is_valid_uri("cloudreve://"));
113    }
114
115    #[test]
116    fn test_uri_to_path() {
117        assert_eq!(
118            uri_to_path("cloudreve://my/path/to/file.txt").unwrap(),
119            "path/to/file.txt"
120        );
121        assert_eq!(uri_to_path("cloudreve://my/").unwrap(), "");
122    }
123
124    #[test]
125    fn test_uri_to_path_invalid() {
126        assert!(uri_to_path("/path/to/file.txt").is_err());
127        assert!(uri_to_path("cloudreve://").is_err());
128    }
129
130    #[test]
131    fn test_paths_to_uris() {
132        let paths = vec!["/file1.txt", "file2.txt", "cloudreve://my/file3.txt"];
133        let uris = paths_to_uris(&paths);
134        assert_eq!(
135            uris,
136            vec![
137                "cloudreve://my/file1.txt",
138                "cloudreve://my/file2.txt",
139                "cloudreve://my/file3.txt"
140            ]
141        );
142    }
143}