flams_ontology/uris/content/
mod.rs

1use crate::languages::Language;
2use crate::uris::content::symbols::SymbolURI;
3use crate::uris::{
4    debugdisplay, ArchiveURIRef, ArchiveURITrait, BaseURI, ModuleURI, Name, PathURITrait,
5    URIOrRefTrait, URIParseError, URIRef, URIRefTrait, URITrait, URIWithLanguage, URI,
6};
7use const_format::concatcp;
8use modules::ModuleURIRef;
9use std::fmt::Display;
10use std::str::FromStr;
11use symbols::SymbolURIRef;
12
13pub(super) mod modules;
14pub(super) mod symbols;
15
16#[cfg(feature = "wasm")]
17#[cfg_attr(
18    feature = "wasm",
19    wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section)
20)]
21const TS_URI: &str = "export type ContentURI = string;";
22
23pub trait ContentURITrait: URIOrRefTrait {
24    fn as_content(&self) -> ContentURIRef;
25    fn module(&self) -> ModuleURIRef;
26}
27
28#[derive(Clone, Hash, PartialEq, Eq)]
29pub enum ContentURI {
30    Module(ModuleURI),
31    Symbol(SymbolURI),
32}
33impl ContentURI {
34    #[inline]
35    #[must_use]
36    #[allow(clippy::missing_const_for_fn)]
37    pub fn name(&self) -> &Name {
38        match self {
39            Self::Module(m) => m.name(),
40            Self::Symbol(s) => s.name(),
41        }
42    }
43}
44impl From<ModuleURI> for ContentURI {
45    #[inline]
46    fn from(value: ModuleURI) -> Self {
47        Self::Module(value)
48    }
49}
50impl From<SymbolURI> for ContentURI {
51    #[inline]
52    fn from(value: SymbolURI) -> Self {
53        Self::Symbol(value)
54    }
55}
56impl URIOrRefTrait for ContentURI {
57    #[inline]
58    fn base(&self) -> &BaseURI {
59        match self {
60            Self::Module(m) => m.base(),
61            Self::Symbol(s) => s.base(),
62        }
63    }
64    #[inline]
65    fn as_uri(&self) -> URIRef {
66        URIRef::Content(self.as_content())
67    }
68}
69impl URITrait for ContentURI {
70    type Ref<'a> = ContentURIRef<'a>;
71}
72impl ContentURITrait for ContentURI {
73    #[inline]
74    fn as_content(&self) -> ContentURIRef {
75        match self {
76            Self::Module(m) => ContentURIRef::Module(m.module()),
77            Self::Symbol(s) => ContentURIRef::Symbol(s),
78        }
79    }
80    #[inline]
81    fn module(&self) -> ModuleURIRef {
82        match self {
83            Self::Module(m) => m.module(),
84            Self::Symbol(s) => s.module(),
85        }
86    }
87}
88
89#[derive(Clone, Copy, Hash, PartialEq, Eq)]
90pub enum ContentURIRef<'a> {
91    Module(ModuleURIRef<'a>),
92    Symbol(SymbolURIRef<'a>),
93}
94impl<'a> From<&'a ContentURI> for ContentURIRef<'a> {
95    #[inline]
96    fn from(value: &'a ContentURI) -> Self {
97        match value {
98            ContentURI::Module(m) => Self::Module(m.module()),
99            ContentURI::Symbol(s) => Self::Symbol(s),
100        }
101    }
102}
103impl<'a> URIOrRefTrait for ContentURIRef<'a> {
104    #[inline]
105    fn base(&self) -> &'a BaseURI {
106        match self {
107            Self::Module(m) => &m.path.archive.base,
108            Self::Symbol(s) => &s.module.path.archive.base,
109        }
110    }
111    #[inline]
112    fn as_uri(&self) -> URIRef<'a> {
113        URIRef::Content(*self)
114    }
115}
116impl<'a> URIRefTrait<'a> for ContentURIRef<'a> {
117    type Owned = ContentURI;
118    #[inline]
119    fn owned(self) -> ContentURI {
120        match self {
121            Self::Module(m) => ContentURI::Module(m.owned()),
122            Self::Symbol(s) => ContentURI::Symbol(s.owned()),
123        }
124    }
125}
126impl<'a> ContentURITrait for ContentURIRef<'a> {
127    #[inline]
128    fn as_content(&self) -> Self {
129        *self
130    }
131    #[inline]
132    fn module(&self) -> ModuleURIRef<'a> {
133        match self {
134            Self::Module(m) => m,
135            Self::Symbol(s) => &s.module,
136        }
137    }
138}
139
140impl Display for ContentURI {
141    #[inline]
142    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143        match self {
144            Self::Module(m) => Display::fmt(m, f),
145            Self::Symbol(s) => Display::fmt(s, f),
146        }
147    }
148}
149debugdisplay!(ContentURI);
150
151impl Display for ContentURIRef<'_> {
152    #[inline]
153    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
154        match self {
155            Self::Module(m) => Display::fmt(m, f),
156            Self::Symbol(s) => Display::fmt(s, f),
157        }
158    }
159}
160debugdisplay!(ContentURIRef<'_>);
161impl ArchiveURITrait for ContentURI {
162    #[inline]
163    fn archive_uri(&self) -> ArchiveURIRef {
164        match self {
165            Self::Module(m) => m.archive_uri(),
166            Self::Symbol(s) => s.module.path.archive_uri(),
167        }
168    }
169}
170impl<'a> ArchiveURITrait for ContentURIRef<'a> {
171    #[inline]
172    fn archive_uri(&self) -> ArchiveURIRef<'a> {
173        match self {
174            Self::Module(m) => m.path.archive_uri(),
175            Self::Symbol(s) => s.module.path.archive_uri(),
176        }
177    }
178}
179
180impl PathURITrait for ContentURI {
181    #[inline]
182    fn as_path(&self) -> crate::uris::PathURIRef {
183        match self {
184            Self::Module(m) => m.as_path(),
185            Self::Symbol(s) => s.as_path(),
186        }
187    }
188    #[inline]
189    fn path(&self) -> Option<&crate::uris::Name> {
190        match self {
191            Self::Module(m) => m.path(),
192            Self::Symbol(s) => s.path(),
193        }
194    }
195}
196impl<'a> PathURITrait for ContentURIRef<'a> {
197    #[inline]
198    fn as_path(&self) -> crate::uris::PathURIRef<'a> {
199        match self {
200            Self::Module(m) => (**m).as_path(),
201            Self::Symbol(s) => s.module.as_path(),
202        }
203    }
204    #[inline]
205    fn path(&self) -> Option<&'a crate::uris::Name> {
206        match self {
207            Self::Module(m) => m.path.path.as_ref(),
208            Self::Symbol(s) => s.module.path.path.as_ref(),
209        }
210    }
211}
212
213impl FromStr for ContentURI {
214    type Err = URIParseError;
215    fn from_str(s: &str) -> Result<Self, Self::Err> {
216        ModuleURI::pre_parse(s, "content uri", |module, mut split| {
217            let Some(c) = split.next() else {
218                return Ok(Self::Module(module));
219            };
220            c.strip_prefix(concatcp!(SymbolURI::SEPARATOR, "="))
221                .map_or_else(
222                    || {
223                        Err(URIParseError::TooManyPartsFor {
224                            uri_kind: "content uri",
225                            original: s.to_string(),
226                        })
227                    },
228                    |name| {
229                        Ok(Self::Symbol(SymbolURI {
230                            module,
231                            name: name.parse()?,
232                        }))
233                    },
234                )
235        })
236    }
237}
238
239#[cfg(feature = "serde")]
240mod serde_impl {
241    use crate::uris::{serialize, ContentURI, ContentURIRef};
242    serialize!(DE ContentURI);
243    serialize!(ContentURIRef<'_>);
244}