valico/json_schema/
helpers.rs

1use serde_json::{Value};
2use url::{Url};
3use url::percent_encoding;
4use uuid::{Uuid};
5
6use super::schema;
7
8pub fn generate_id() -> Url {
9    let uuid = Uuid::new_v4();
10    Url::parse(&format!("json-schema://{}", uuid)).unwrap()
11}
12
13/// http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
14pub fn encode(string: &str) -> String {
15    percent_encoding::percent_encode(
16        string
17            .replace("~", "~0")
18            .replace("/", "~1")
19            .replace("%", "%25")
20            .as_bytes(),
21        percent_encoding::QUERY_ENCODE_SET
22    ).to_string()
23}
24
25/// Encode and connect
26pub fn connect(strings: &[&str]) -> String {
27    strings.iter().map(|s| encode(s)).collect::<Vec<String>>().join("/")
28}
29
30pub fn parse_url_key(key: &str, obj: &Value) -> Result<Option<Url>, schema::SchemaError> {
31    match obj.get(key) {
32        Some(value) => {
33            match value.as_str() {
34                Some(string) => Url::parse(string)
35                                .map(|url| Some(url))
36                                .map_err(|err| schema::SchemaError::UrlParseError(err)),
37                None => Ok(None)
38            }
39        },
40        None => Ok(None)
41    }
42}
43
44pub fn parse_url_key_with_base(key: &str, obj: &Value, base: &Url) -> Result<Option<Url>, schema::SchemaError> {
45    match obj.get(key) {
46        Some(value) => {
47            match value.as_str() {
48                Some(string) => Url::options()
49                                .base_url(Some(base))
50                                .parse(string)
51                                .map(|url| Some(url))
52                                .map_err(|err| schema::SchemaError::UrlParseError(err)),
53                None => Ok(None)
54            }
55        },
56        None => Ok(None)
57    }
58}
59
60pub fn alter_fragment_path(mut url: Url, new_fragment: String) -> Url {
61
62    let normalized_fragment = if new_fragment.starts_with("/") {
63        &new_fragment[1..]
64    } else {
65        new_fragment.as_ref()
66    };
67
68    let result_fragment = match url.fragment() {
69        Some(ref fragment) if fragment.len() > 0 => {
70            if !fragment.starts_with("/") {
71                let mut result_fragment = "".to_string();
72                let mut fragment_parts = fragment.split("/").map(|s| s.to_string());
73                result_fragment.push_str("#");
74                result_fragment.push_str(fragment_parts.next().unwrap().as_ref());
75                result_fragment.push_str("/");
76                result_fragment.push_str(normalized_fragment.as_ref());
77                result_fragment
78            } else {
79                "/".to_string() + normalized_fragment
80            }
81        },
82        _ => "/".to_string() + normalized_fragment
83    };
84
85    url.set_fragment(Some(&result_fragment));
86    url
87}
88
89pub fn serialize_schema_path(url: &Url) -> (String, Option<String>) {
90    let mut url_without_fragment = url.clone();
91    url_without_fragment.set_fragment(None);
92    let mut url_str = url_without_fragment.into_string();
93
94    match url.fragment().as_ref() {
95        Some(fragment) if fragment.len() > 0 => {
96            if !fragment.starts_with("/") {
97                let fragment_parts = fragment.split("/").map(|s| s.to_string()).collect::<Vec<String>>();
98                url_str.push_str("#");
99                url_str.push_str(fragment_parts[0].as_ref());
100                let fragment = if fragment_parts.len() > 1 {
101                    Some("/".to_string() + fragment_parts[1..].join("/").as_ref())
102                } else {
103                    None
104                };
105                (url_str, fragment)
106            } else {
107                (url_str, Some(fragment.to_string()))
108            }
109
110        },
111        _ => (url_str, None)
112    }
113}