libsubconverter/utils/url.rs
1//! URL encoding/decoding utilities
2
3
4/// Encodes a string using URL encoding
5///
6/// # Arguments
7/// * `input` - The string to encode
8///
9/// # Returns
10/// * String containing the URL-encoded input
11///
12/// # Examples
13/// ```
14/// use subconverter_rs::utils::url::url_encode;
15///
16/// let encoded = url_encode("Hello World!");
17/// assert_eq!(encoded, "Hello%20World%21");
18/// ```
19pub fn url_encode(input: &str) -> String {
20 urlencoding::encode(input).into_owned()
21}
22
23/// Decodes a URL-encoded string
24///
25/// # Arguments
26/// * `input` - The URL-encoded string to decode
27///
28/// # Returns
29/// * String containing the decoded input
30/// * Returns the original string if decoding fails
31///
32/// # Examples
33/// ```
34/// use subconverter_rs::utils::url::url_decode;
35///
36/// let decoded = url_decode("Hello%20World%21");
37/// assert_eq!(decoded, "Hello World!");
38/// ```
39pub fn url_decode(input: &str) -> String {
40 urlencoding::decode(input)
41 .map(|cow| cow.into_owned())
42 .unwrap_or_else(|_| input.to_string())
43}
44
45/// Extracts a parameter value from a URL query string
46///
47/// # Arguments
48/// * `url_params` - The URL query string containing parameters
49/// * `param_name` - The name of the parameter to extract
50///
51/// # Returns
52/// * String containing the parameter value if found, or an empty string if not found
53///
54/// # Examples
55/// ```
56/// use subconverter_rs::utils::url::get_url_arg;
57///
58/// let query = "host=example.com&port=443&mode=ws";
59/// assert_eq!(get_url_arg(query, "host"), "example.com");
60/// assert_eq!(get_url_arg(query, "port"), "443");
61/// assert_eq!(get_url_arg(query, "unknown"), "");
62/// ```
63pub fn get_url_arg(url_params: &str, param_name: &str) -> String {
64 let pattern = format!("{}=", param_name);
65 let mut pos = url_params.len();
66
67 while pos > 0 {
68 // Find the pattern starting from pos, moving backward
69 if let Some(found_pos) = url_params[..pos].rfind(&pattern) {
70 // Check if this is a proper parameter boundary
71 if found_pos == 0
72 || url_params.as_bytes()[found_pos - 1] == b'&'
73 || url_params.as_bytes()[found_pos - 1] == b'?'
74 {
75 // Extract the value
76 let start = found_pos + pattern.len();
77 let end = match url_params[start..].find('&') {
78 Some(ampersand_pos) => start + ampersand_pos,
79 None => url_params.len(),
80 };
81 return url_params[start..end].to_string();
82 }
83 // Move position backward to continue searching
84 pos = found_pos;
85 } else {
86 // Pattern not found
87 break;
88 }
89
90 // Prevent unsigned integer underflow
91 if pos == 0 {
92 break;
93 }
94 pos -= 1;
95 }
96
97 // Parameter not found
98 String::new()
99}