rustbasic_core/
serde_urlencoded.rs1
2pub fn from_str<T: serde::de::DeserializeOwned>(s: &str) -> Result<T, String> {
4 let mut map = serde_json::Map::new();
5 for pair in s.split('&') {
6 if pair.is_empty() {
7 continue;
8 }
9 let mut parts = pair.splitn(2, '=');
10 let key = parts.next().unwrap_or("");
11 let val = parts.next().unwrap_or("");
12
13 let decoded_key = url_decode(key)?;
14 let decoded_val = url_decode(val)?;
15
16 map.insert(decoded_key, serde_json::Value::String(decoded_val));
17 }
18 serde_json::from_value(serde_json::Value::Object(map))
19 .map_err(|e| e.to_string())
20}
21
22pub fn from_bytes<T: serde::de::DeserializeOwned>(bytes: &[u8]) -> Result<T, String> {
24 let s = std::str::from_utf8(bytes).map_err(|e| e.to_string())?;
25 from_str(s)
26}
27
28fn url_decode(s: &str) -> Result<String, String> {
29 let mut decoded = String::new();
30 let mut chars = s.chars();
31 while let Some(c) = chars.next() {
32 if c == '+' {
33 decoded.push(' ');
34 } else if c == '%' {
35 let h0 = chars.next().ok_or("Format URL-encoded tidak valid")?;
36 let h1 = chars.next().ok_or("Format URL-encoded tidak valid")?;
37 let hex_str = format!("{}{}", h0, h1);
38 let byte = u8::from_str_radix(&hex_str, 16)
39 .map_err(|e| e.to_string())?;
40 decoded.push(byte as char);
41 } else {
42 decoded.push(c);
43 }
44 }
45 Ok(decoded)
46}