graph_http/url/
graphurl.rs

1use graph_error::GraphFailure;
2use std::ffi::OsStr;
3use std::ops::{Deref, Index, Range, RangeFrom, RangeFull, RangeTo};
4use std::str::FromStr;
5use url::form_urlencoded::Serializer;
6use url::{PathSegmentsMut, Position, Url, UrlQuery};
7
8#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
9pub struct GraphUrl {
10    url: Url,
11}
12
13impl GraphUrl {
14    pub fn parse(input: &str) -> Result<Self, GraphFailure> {
15        Ok(GraphUrl {
16            url: Url::parse(input)?,
17        })
18    }
19
20    pub fn as_str(&self) -> &str {
21        self.url.as_str()
22    }
23
24    pub fn set_host(&mut self, host: &str) {
25        self.url.set_host(Some(host)).unwrap_or_default();
26    }
27
28    pub fn host(&self) -> Option<&str> {
29        self.url.host_str()
30    }
31
32    pub fn path(&self) -> &str {
33        self.url.path()
34    }
35
36    pub fn set_path<I: AsRef<str>>(&mut self, path: I) {
37        self.url.set_path(path.as_ref());
38    }
39
40    pub fn extend_path<I: AsRef<str>>(&mut self, path: &[I]) {
41        if let Ok(mut p) = self.url.path_segments_mut() {
42            p.extend(path);
43        }
44    }
45
46    pub fn query(&self) -> Option<&str> {
47        self.url.query()
48    }
49
50    pub fn set_query<I: AsRef<str>>(&mut self, query: I) {
51        self.url.set_query(Some(query.as_ref()));
52    }
53
54    pub fn append_query_pair<KV: AsRef<str>>(&mut self, key: KV, value: KV) {
55        self.url
56            .query_pairs_mut()
57            .append_pair(key.as_ref(), value.as_ref());
58    }
59
60    #[allow(clippy::result_unit_err)]
61    pub fn path_segments_mutable(&mut self) -> Result<PathSegmentsMut, ()> {
62        self.url.path_segments_mut()
63    }
64
65    pub fn extend_path_os_str_lossy(&mut self, path: &[&OsStr]) -> &mut Self {
66        if let Ok(mut p) = self.url.path_segments_mut() {
67            p.extend(path.iter().map(|s| s.to_string_lossy()));
68        }
69        self
70    }
71
72    pub fn to_url(&self) -> Url {
73        self.url.clone()
74    }
75
76    pub fn to_reqwest_url(&self) -> Url {
77        Url::parse(self.as_str()).unwrap()
78    }
79
80    pub fn query_pairs_mutable(&mut self) -> Serializer<UrlQuery> {
81        self.url.query_pairs_mut()
82    }
83
84    pub fn starts_with(&self, start: &str) -> bool {
85        self.as_str().starts_with(start)
86    }
87
88    pub fn ends_with(&self, end: &str) -> bool {
89        self.as_str().ends_with(end)
90    }
91
92    pub fn replace(&mut self, input: &str) -> Result<(), GraphFailure> {
93        self.url = Url::parse(input)?;
94        Ok(())
95    }
96
97    /// Retrieves the total count of matching resources.
98    /// [See the docs](https://docs.microsoft.com/en-us/graph/query-parameters#count-parameter)
99    pub fn count(&mut self, value: &str) {
100        self.append_query_pair("$count", value);
101    }
102
103    /// Filters properties (columns).
104    /// [See the docs](https://docs.microsoft.com/en-us/graph/query-parameters#select-parameter)
105    pub fn select(&mut self, value: &[&str]) {
106        let s = value.join(",");
107        self.append_query_pair("$select", &s);
108    }
109
110    /// Retrieves related resources.
111    /// [See the docs](https://docs.microsoft.com/en-us/graph/query-parameters#expand-parameter)
112    pub fn expand(&mut self, value: &[&str]) {
113        let s = value.join(" ");
114        self.append_query_pair("$expand", &s);
115    }
116
117    /// Filters results (rows).
118    /// [See the docs](https://docs.microsoft.com/en-us/graph/query-parameters#filter-parameter)
119    pub fn filter(&mut self, value: &[&str]) {
120        let s = value.join(",");
121        self.append_query_pair("$filter", &s);
122    }
123
124    /// Orders results.
125    /// [See the docs](https://docs.microsoft.com/en-us/graph/query-parameters#orderby-parameter)
126    pub fn order_by(&mut self, value: &[&str]) {
127        let s = value.join(" ");
128        self.append_query_pair("$orderby", &s);
129    }
130
131    /// Returns results based on search criteria.
132    /// [See the docs](https://docs.microsoft.com/en-us/graph/query-parameters#search-parameter)
133    pub fn search(&mut self, value: &str) {
134        self.append_query_pair("$search", value);
135    }
136
137    /// Returns the results in the specified media format.
138    /// [See the docs](https://docs.microsoft.com/en-us/graph/query-parameters#format-parameter)
139    pub fn format(&mut self, value: &str) {
140        self.append_query_pair("$format", value);
141    }
142
143    /// Indexes into a result set. Also used by some APIs to implement paging and can be used
144    /// together with $top to manually page results.
145    /// [See the docs](https://docs.microsoft.com/en-us/graph/query-parameters#skip-parameter)
146    pub fn skip(&mut self, value: &str) {
147        self.append_query_pair("$skip", value.as_ref());
148    }
149
150    /// Retrieves the next page of results from result sets that span multiple pages.
151    /// (Some APIs use $skip instead.)
152    /// [See the docs](https://docs.microsoft.com/en-us/graph/query-parameters#skiptoken-parameter)
153    pub fn skip_token(&mut self, value: &str) {
154        self.append_query_pair("$skipToken", value.as_ref());
155    }
156
157    /// Sets the page size of results.
158    /// [See the docs](https://docs.microsoft.com/en-us/graph/query-parameters#top-parameter)
159    pub fn top(&mut self, value: &str) {
160        self.append_query_pair("$top", value.as_ref());
161    }
162
163    pub fn cast(&mut self, value: &str) {
164        self.extend_path(&[value]);
165    }
166}
167
168impl From<Url> for GraphUrl {
169    fn from(url: Url) -> Self {
170        GraphUrl { url }
171    }
172}
173
174impl From<&Url> for GraphUrl {
175    fn from(url: &Url) -> Self {
176        GraphUrl { url: url.clone() }
177    }
178}
179
180impl FromStr for GraphUrl {
181    type Err = GraphFailure;
182
183    fn from_str(s: &str) -> Result<Self, Self::Err> {
184        GraphUrl::parse(s)
185    }
186}
187
188impl Index<RangeFull> for GraphUrl {
189    type Output = str;
190
191    fn index(&self, _: RangeFull) -> &Self::Output {
192        &self.url[..]
193    }
194}
195
196impl Index<RangeFrom<Position>> for GraphUrl {
197    type Output = str;
198
199    fn index(&self, index: RangeFrom<Position>) -> &Self::Output {
200        &self.url[index]
201    }
202}
203
204impl Index<RangeTo<Position>> for GraphUrl {
205    type Output = str;
206
207    fn index(&self, index: RangeTo<Position>) -> &Self::Output {
208        &self.url[index]
209    }
210}
211
212impl Index<Range<Position>> for GraphUrl {
213    type Output = str;
214
215    fn index(&self, index: Range<Position>) -> &Self::Output {
216        &self.url[index]
217    }
218}
219
220impl AsRef<str> for GraphUrl {
221    fn as_ref(&self) -> &str {
222        self.as_str()
223    }
224}
225
226impl AsRef<Url> for GraphUrl {
227    fn as_ref(&self) -> &Url {
228        &self.url
229    }
230}
231
232impl AsMut<Url> for GraphUrl {
233    fn as_mut(&mut self) -> &mut Url {
234        &mut self.url
235    }
236}
237
238impl ToString for GraphUrl {
239    fn to_string(&self) -> String {
240        self.url[..].to_string()
241    }
242}
243
244impl Deref for GraphUrl {
245    type Target = str;
246
247    fn deref(&self) -> &Self::Target {
248        self.url.as_str()
249    }
250}
251
252impl Default for GraphUrl {
253    fn default() -> Self {
254        GraphUrl::parse("https://graph.microsoft.com/v1.0").unwrap()
255    }
256}