flams_ontology/uris/
paths.rs1use crate::uris::archives::ArchiveURIRef;
2use crate::uris::errors::URIParseError;
3use crate::uris::macros::debugdisplay;
4use crate::uris::{
5 ArchiveURI, ArchiveURITrait, BaseURI, Name, URIOrRefTrait, URIRef, URIRefTrait, URITrait, URI,
6};
7use const_format::concatcp;
8use either::Either;
9use flams_utils::parsing::StringOrStr;
10use std::fmt::Display;
11use std::str::{FromStr, Split};
12
13#[derive(Clone, PartialEq, Eq, Hash)]
14pub struct PathURI {
15 pub(super) archive: ArchiveURI,
16 pub(super) path: Option<Name>,
17}
18impl From<ArchiveURI> for PathURI {
19 #[inline]
20 fn from(archive: ArchiveURI) -> Self {
21 Self {
22 archive,
23 path: None,
24 }
25 }
26}
27impl PathURI {
28 pub const SEPARATOR: char = 'p';
29 #[inline]
30 #[must_use]
31 #[allow(clippy::missing_const_for_fn)]
32 pub fn path(&self) -> Option<&Name> {
33 self.path.as_ref()
34 }
35 #[inline]
36 #[must_use]
37 pub fn up(mut self) -> Self {
38 if let Some(name) = &mut self.path {
39 name.0.pop();
40 if name.0.is_empty() {
41 self.path = None
42 }
43 }
44 self
45 }
46}
47impl Display for PathURI {
48 #[inline]
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 Display::fmt(&self.as_path(), f)
51 }
52}
53debugdisplay!(PathURI);
54
55impl URIOrRefTrait for PathURI {
56 #[inline]
57 fn base(&self) -> &BaseURI {
58 &self.archive.base
59 }
60 #[inline]
61 fn as_uri(&self) -> URIRef {
62 URIRef::Path(self.as_path())
63 }
64}
65impl URITrait for PathURI {
66 type Ref<'a> = PathURIRef<'a>;
67}
68impl ArchiveURITrait for PathURI {
69 #[inline]
70 fn archive_uri(&self) -> ArchiveURIRef {
71 self.archive.archive_uri()
72 }
73}
74
75#[derive(Clone, Copy, PartialEq, Eq, Hash)]
76pub struct PathURIRef<'a> {
77 pub(super) archive: ArchiveURIRef<'a>,
78 pub(super) path: Option<&'a Name>,
79}
80impl<'a> From<&'a PathURI> for PathURIRef<'a> {
81 #[inline]
82 fn from(value: &'a PathURI) -> Self {
83 Self {
84 archive: value.archive.archive_uri(),
85 path: value.path.as_ref(),
86 }
87 }
88}
89impl<'a> URIOrRefTrait for PathURIRef<'a> {
90 #[inline]
91 fn base(&self) -> &'a BaseURI {
92 self.archive.base
93 }
94 #[inline]
95 fn as_uri(&self) -> URIRef<'a> {
96 URIRef::Path(*self)
97 }
98}
99impl<'a> URIRefTrait<'a> for PathURIRef<'a> {
100 type Owned = PathURI;
101 #[inline]
102 fn owned(self) -> PathURI {
103 PathURI {
104 archive: self.archive.owned(),
105 path: self.path.cloned(),
106 }
107 }
108}
109impl Display for PathURIRef<'_> {
110 #[inline]
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 if let Some(path) = self.path {
113 write!(f, "{}&{}={}", self.archive, PathURI::SEPARATOR, path)
114 } else {
115 Display::fmt(&self.archive, f)
116 }
117 }
118}
119debugdisplay!(PathURIRef<'_>);
120
121pub trait PathURITrait: ArchiveURITrait {
122 fn as_path(&self) -> PathURIRef;
123 #[inline]
124 fn path(&self) -> Option<&Name> {
125 self.as_path().path
126 }
127}
128impl PathURITrait for PathURI {
129 fn as_path(&self) -> PathURIRef {
130 PathURIRef {
131 archive: self.archive.archive_uri(),
132 path: self.path.as_ref(),
133 }
134 }
135}
136impl PathURITrait for PathURIRef<'_> {
137 #[inline]
138 fn as_path(&self) -> Self {
139 *self
140 }
141}
142impl<'a> ArchiveURITrait for PathURIRef<'a> {
143 #[inline]
144 fn archive_uri(&self) -> ArchiveURIRef<'a> {
145 self.archive
146 }
147}
148impl PathURI {
149 pub(super) fn pre_parse<R>(
150 s: &str,
151 uri_kind: &'static str,
152 f: impl FnOnce(Self, Option<&str>, Split<char>) -> Result<R, URIParseError>,
153 ) -> Result<R, URIParseError> {
154 ArchiveURI::pre_parse(s, uri_kind, |archive, mut split| {
155 let (p, n) = if let Some(p) = split.next() {
156 if let Some(p) = p.strip_prefix(concatcp!(PathURI::SEPARATOR, "=")) {
157 (
158 Self {
159 archive,
160 path: Some(p.parse()?),
161 },
162 None,
163 )
164 } else {
165 (
166 Self {
167 archive,
168 path: None,
169 },
170 Some(p),
171 )
172 }
173 } else {
174 (
175 Self {
176 archive,
177 path: None,
178 },
179 None,
180 )
181 };
182 f(p, n, split)
183 })
184 }
185}
186impl FromStr for PathURI {
187 type Err = URIParseError;
188 fn from_str(s: &str) -> Result<Self, Self::Err> {
189 Self::pre_parse(s, "path uri", |u, next, mut split| {
190 if next.is_some() || split.next().is_some() {
191 return Err(URIParseError::TooManyPartsFor {
192 uri_kind: "path uri",
193 original: s.to_string(),
194 });
195 }
196 Ok(u)
197 })
198 }
199}
200
201#[cfg(feature = "serde")]
202mod serde_impl {
203 use super::{PathURI, PathURIRef};
204 use crate::uris::serialize;
205 serialize!(DE PathURI);
206 serialize!(PathURIRef<'_>);
207}