1use std::borrow::Cow;
8
9use serde::Serialize;
10use url::Url;
11
12pub trait Route {
13 type Query: Serialize;
14 fn route() -> &'static str;
15 fn query(&self) -> Option<&Self::Query> {
16 None
17 }
18
19 fn path(&self) -> Cow<'static, str> {
20 Cow::Borrowed(Self::route())
21 }
22
23 fn path_and_query(&self) -> Cow<'static, str> {
24 let path = self.path();
25 if let Some(query) = self.query() {
26 let query = serde_urlencoded::to_string(query).unwrap();
27
28 if query.is_empty() {
29 path
30 } else {
31 format!("{path}?{query}").into()
32 }
33 } else {
34 path
35 }
36 }
37
38 fn absolute_url(&self, base: &Url) -> Url {
39 let relative = self.path_and_query();
40 let relative = relative.trim_start_matches('/');
41 base.join(relative).unwrap()
42 }
43}
44
45pub trait SimpleRoute {
46 const PATH: &'static str;
47}
48
49impl<T: SimpleRoute> Route for T {
50 type Query = ();
51 fn route() -> &'static str {
52 Self::PATH
53 }
54}