1use serde::{Deserialize, Serialize, Serializer};
2
3#[derive(Serialize, Deserialize, Debug, Clone)]
5pub struct Reference(ReferenceInner);
6
7impl Reference {
8 pub fn new_relative(relative: &str) -> Self {
10 Self(ReferenceInner::Relative(RelativeReference(
11 relative.to_string(),
12 )))
13 }
14 pub fn new_absolute(absolute: &str) -> Self {
16 Self(ReferenceInner::Absolute(absolute.to_string()))
17 }
18}
19
20#[derive(Serialize, Deserialize, Debug, Clone)]
21#[serde(untagged)]
22enum ReferenceInner {
23 Absolute(String),
24 #[serde(skip_deserializing)]
25 Relative(RelativeReference),
26}
27
28#[cfg(feature = "tokio")]
29tokio::task_local! {
30 #[doc(hidden)]
31 pub static BASE_URL: String;
32}
33
34#[derive(Debug, Clone)]
35struct RelativeReference(String);
36
37impl Serialize for RelativeReference {
38 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
39 where
40 S: Serializer,
41 {
42 #[cfg(feature = "tokio")]
43 let absolute_url = BASE_URL
44 .try_with(|base_url| format!("{}{}", base_url, self.0))
45 .unwrap_or(self.0.clone());
46 #[cfg(not(feature = "tokio"))]
47 let absolute_url = self.0.clone();
48 serializer.serialize_str(&absolute_url)
49 }
50}