flams_ontology/uris/content/
symbols.rs1use crate::languages::Language;
2use const_format::concatcp;
3use std::fmt::Display;
4use std::str::{FromStr, Split};
5
6use crate::uris::{
7 debugdisplay, ArchiveURI, ArchiveURIRef, ArchiveURITrait, BaseURI, ContentURIRef,
8 ContentURITrait, ModuleURI, Name, PathURIRef, PathURITrait, URIOrRefTrait, URIParseError,
9 URIRef, URIRefTrait, URITrait, URIWithLanguage, URI,
10};
11
12use super::modules::ModuleURIRef;
13use super::ContentURI;
14
15#[cfg(feature = "wasm")]
16#[cfg_attr(
17 feature = "wasm",
18 wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section)
19)]
20const TS_URI: &str = "export type SymbolURI = string;";
21
22#[derive(Clone, PartialEq, Eq, Hash)]
23pub struct SymbolURI {
24 pub(in crate::uris) module: ModuleURI,
25 pub(in crate::uris) name: Name,
26}
27impl SymbolURI {
28 pub const SEPARATOR: char = 's';
29 #[must_use]
30 #[allow(clippy::missing_const_for_fn)]
31 pub fn new(module: ModuleURI, name: Name) -> Self {
32 Self { module, name }
33 }
34 #[must_use]
35 pub fn into_module(self) -> ModuleURI {
36 self.module / self.name
37 }
38}
39impl Display for SymbolURI {
40 #[inline]
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 write!(f, "{}&{}={}", self.module, Self::SEPARATOR, self.name)
43 }
44}
45debugdisplay!(SymbolURI);
46
47pub type SymbolURIRef<'a> = &'a SymbolURI;
63
64impl URITrait for SymbolURI {
65 type Ref<'a> = SymbolURIRef<'a>;
66}
67impl<'a> URIRefTrait<'a> for SymbolURIRef<'a> {
68 type Owned = SymbolURI;
69 #[inline]
70 fn owned(self) -> SymbolURI {
71 self.clone()
72 }
73}
74impl From<SymbolURI> for URI {
75 #[inline]
76 fn from(u: SymbolURI) -> Self {
77 Self::Content(ContentURI::Symbol(u))
78 }
79}
80impl<'a> From<SymbolURIRef<'a>> for URIRef<'a> {
81 #[inline]
82 fn from(u: SymbolURIRef<'a>) -> Self {
83 URIRef::Content(ContentURIRef::Symbol(u))
84 }
85}
86impl URIOrRefTrait for SymbolURI {
110 #[inline]
111 fn base(&self) -> &BaseURI {
112 self.module.base()
113 }
114 #[inline]
115 fn as_uri(&self) -> URIRef {
116 URIRef::Content(self.as_content())
117 }
118}
119
120impl ContentURITrait for SymbolURI {
121 #[inline]
122 fn as_content(&self) -> ContentURIRef {
123 ContentURIRef::Symbol(self)
124 }
125 #[inline]
126 fn module(&self) -> ModuleURIRef {
127 &self.module
128 }
129}
130impl<'a> ContentURITrait for SymbolURIRef<'a> {
131 #[inline]
132 fn as_content(&self) -> ContentURIRef<'a> {
133 ContentURIRef::Symbol(self)
134 }
135 #[inline]
136 fn module(&self) -> ModuleURIRef<'a> {
137 &self.module
138 }
139}
140
141impl SymbolURI {
142 #[inline]
143 #[must_use]
144 pub const fn name(&self) -> &Name {
145 &self.name
146 }
147 pub(super) fn pre_parse<R>(
148 s: &str,
149 uri_kind: &'static str,
150 f: impl FnOnce(Self, Split<char>) -> Result<R, URIParseError>,
151 ) -> Result<R, URIParseError> {
152 ModuleURI::pre_parse(s, uri_kind, |module, mut split| {
153 let Some(s) = split.next() else {
154 return Err(URIParseError::MissingPartFor {
155 uri_kind,
156 part: "symbol name",
157 original: s.to_string(),
158 });
159 };
160 s.strip_prefix(concatcp!(SymbolURI::SEPARATOR, "="))
161 .map_or_else(
162 || {
163 Err(URIParseError::MissingPartFor {
164 uri_kind,
165 part: "symbol name",
166 original: s.to_string(),
167 })
168 },
169 |name| {
170 f(
171 Self {
172 module,
173 name: name.parse()?,
174 },
175 split,
176 )
177 },
178 )
179 })
180 }
181}
182impl FromStr for SymbolURI {
183 type Err = URIParseError;
184 fn from_str(s: &str) -> Result<Self, Self::Err> {
185 Self::pre_parse(s, "symbol uri", |u, mut split| {
186 if split.next().is_some() {
187 return Err(URIParseError::TooManyPartsFor {
188 uri_kind: "symbol uri",
189 original: s.to_string(),
190 });
191 }
192 Ok(u)
193 })
194 }
195}
196impl ArchiveURITrait for SymbolURI {
197 #[inline]
198 fn archive_uri(&self) -> ArchiveURIRef {
199 self.module.archive_uri()
200 }
201}
202impl PathURITrait for SymbolURI {
203 #[inline]
204 fn as_path(&self) -> PathURIRef {
205 self.module.as_path()
206 }
207 #[inline]
208 fn path(&self) -> Option<&Name> {
209 self.module.path()
210 }
211}
212impl<'a> ArchiveURITrait for SymbolURIRef<'a> {
213 #[inline]
214 fn archive_uri(&self) -> ArchiveURIRef<'a> {
215 self.module.path.archive_uri()
216 }
217}
218impl<'a> PathURITrait for SymbolURIRef<'a> {
219 #[inline]
220 fn as_path(&self) -> PathURIRef<'a> {
221 self.module.as_path()
222 }
223 #[inline]
224 fn path(&self) -> Option<&Name> {
225 self.module.path.path.as_ref()
226 }
227}
228
229#[cfg(feature = "serde")]
230mod serde_impl {
231 use crate::uris::{serialize, SymbolURI, SymbolURIRef};
232 serialize!(DE SymbolURI);
233 }
235
236#[cfg(feature = "tantivy")]
237impl tantivy::schema::document::ValueDeserialize for SymbolURI {
238 fn deserialize<'de, D>(
239 deserializer: D,
240 ) -> Result<Self, tantivy::schema::document::DeserializeError>
241 where
242 D: tantivy::schema::document::ValueDeserializer<'de>,
243 {
244 deserializer
245 .deserialize_string()?
246 .parse()
247 .map_err(|_| tantivy::schema::document::DeserializeError::custom(""))
248 }
249}