graph_http/url/
graphurl.rs1use 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 pub fn count(&mut self, value: &str) {
100 self.append_query_pair("$count", value);
101 }
102
103 pub fn select(&mut self, value: &[&str]) {
106 let s = value.join(",");
107 self.append_query_pair("$select", &s);
108 }
109
110 pub fn expand(&mut self, value: &[&str]) {
113 let s = value.join(" ");
114 self.append_query_pair("$expand", &s);
115 }
116
117 pub fn filter(&mut self, value: &[&str]) {
120 let s = value.join(",");
121 self.append_query_pair("$filter", &s);
122 }
123
124 pub fn order_by(&mut self, value: &[&str]) {
127 let s = value.join(" ");
128 self.append_query_pair("$orderby", &s);
129 }
130
131 pub fn search(&mut self, value: &str) {
134 self.append_query_pair("$search", value);
135 }
136
137 pub fn format(&mut self, value: &str) {
140 self.append_query_pair("$format", value);
141 }
142
143 pub fn skip(&mut self, value: &str) {
147 self.append_query_pair("$skip", value.as_ref());
148 }
149
150 pub fn skip_token(&mut self, value: &str) {
154 self.append_query_pair("$skipToken", value.as_ref());
155 }
156
157 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}