identity_kit/did/
reference.rs1use core::fmt;
4use core::str::FromStr;
5
6use serde::de::Error as _;
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8
9use super::syntax::{check_len, scan_url_suffix};
10use super::{DEFAULT_MAX_LEN, Did, DidError, DidUrl};
11
12#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
39pub enum DidUrlReference {
40 Absolute(DidUrl),
42 Relative(String),
44}
45
46impl DidUrlReference {
47 pub fn parse(s: &str) -> Result<Self, DidError> {
56 if s.starts_with(['/', '?', '#']) {
57 check_len(s, DEFAULT_MAX_LEN)?;
58 scan_url_suffix(s, 0)?;
59 Ok(Self::Relative(s.to_owned()))
60 } else {
61 DidUrl::parse(s).map(Self::Absolute)
62 }
63 }
64
65 pub fn is_relative(&self) -> bool {
67 matches!(self, Self::Relative(_))
68 }
69
70 pub fn as_str(&self) -> &str {
72 match self {
73 Self::Absolute(url) => url.as_str(),
74 Self::Relative(s) => s,
75 }
76 }
77
78 pub fn resolve(&self, base: &Did) -> Result<DidUrl, DidError> {
86 match self {
87 Self::Absolute(url) => Ok(url.clone()),
88 Self::Relative(s) => base.join(s),
89 }
90 }
91
92 pub fn refers_to(&self, url: &DidUrl, base: &Did) -> bool {
94 match self {
95 Self::Absolute(this) => this == url,
96 Self::Relative(_) => self.resolve(base).is_ok_and(|resolved| &resolved == url),
97 }
98 }
99}
100
101impl fmt::Display for DidUrlReference {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 f.write_str(self.as_str())
104 }
105}
106
107impl AsRef<str> for DidUrlReference {
108 fn as_ref(&self) -> &str {
109 self.as_str()
110 }
111}
112
113impl FromStr for DidUrlReference {
114 type Err = DidError;
115
116 fn from_str(s: &str) -> Result<Self, Self::Err> {
117 Self::parse(s)
118 }
119}
120
121impl TryFrom<&str> for DidUrlReference {
122 type Error = DidError;
123
124 fn try_from(s: &str) -> Result<Self, Self::Error> {
125 Self::parse(s)
126 }
127}
128
129impl TryFrom<String> for DidUrlReference {
130 type Error = DidError;
131
132 fn try_from(s: String) -> Result<Self, Self::Error> {
133 Self::parse(&s)
134 }
135}
136
137impl From<DidUrl> for DidUrlReference {
138 fn from(url: DidUrl) -> Self {
139 Self::Absolute(url)
140 }
141}
142
143impl From<&DidUrl> for DidUrlReference {
144 fn from(url: &DidUrl) -> Self {
145 Self::Absolute(url.clone())
146 }
147}
148
149impl Serialize for DidUrlReference {
150 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
151 serializer.serialize_str(self.as_str())
152 }
153}
154
155impl<'de> Deserialize<'de> for DidUrlReference {
156 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
157 let s = String::deserialize(deserializer)?;
158 Self::parse(&s).map_err(D::Error::custom)
159 }
160}