flams_ontology/uris/narrative/
document_elements.rs

1use crate::languages::Language;
2use crate::uris::{
3    debugdisplay, ArchiveURI, ArchiveURIRef, ArchiveURITrait, BaseURI, ContentURIRef, ContentURITrait, DocumentURI, ModuleURI, Name, NarrativeURIRef, NarrativeURITrait, PathURIRef, PathURITrait, SymbolURI, URIOrRefTrait, URIParseError, URIRef, URIRefTrait, URITrait, URIWithLanguage, URI
4};
5use const_format::concatcp;
6use std::fmt::Display;
7use std::str::{FromStr, Split};
8
9use super::NarrativeURI;
10
11#[cfg(feature = "wasm")]
12#[cfg_attr(feature = "wasm", wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section))]
13const TS_URI: &str = "export type DocumentElementURI = string;";
14
15
16#[derive(Clone, PartialEq, Eq, Hash)]
17pub struct DocumentElementURI {
18    pub(in crate::uris) document: DocumentURI,
19    pub(in crate::uris) name: Name,
20}
21impl DocumentElementURI {
22    pub const SEPARATOR: char = 'e';
23    #[inline]
24    #[must_use]
25    pub const fn document(&self) -> &DocumentURI {
26        &self.document
27    }
28
29    #[inline]
30    #[must_use]
31    pub const fn name(&self) -> &Name {
32        &self.name
33    }
34
35    #[must_use]
36    pub fn parent(&self) -> Self {
37        if self.name.is_simple() { return self.clone() }
38        let steps = self.name.steps();
39        let steps = &steps[0..steps.len()-1];
40        let name = Name(steps.into());
41        Self {
42            document: self.document.clone(),
43            name
44        }
45    }
46}
47impl Display for DocumentElementURI {
48    #[inline]
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        write!(f, "{}&{}={}", self.document, Self::SEPARATOR, self.name)
51    }
52}
53debugdisplay!(DocumentElementURI);
54impl URIOrRefTrait for DocumentElementURI {
55    #[inline]
56    fn base(&self) -> &BaseURI {
57        self.document.base()
58    }
59    #[inline]
60    fn as_uri(&self) -> URIRef {
61        URIRef::Narrative(self.as_narrative())
62    }
63}
64impl URIWithLanguage for DocumentElementURI {
65    #[inline]
66    fn language(&self) -> Language {
67        self.document.language
68    }
69}
70impl NarrativeURITrait for DocumentElementURI {
71    #[inline]
72    fn as_narrative(&self) -> NarrativeURIRef {
73        NarrativeURIRef::Element(self)
74    }
75    #[inline]
76    fn document(&self) -> &DocumentURI {
77        &self.document
78    }
79}
80impl URITrait for DocumentElementURI {
81    type Ref<'a> = &'a Self;
82}
83impl From<DocumentElementURI> for URI {
84    #[inline]
85    fn from(value: DocumentElementURI) -> Self {
86        Self::Narrative(NarrativeURI::Element(value))
87    }
88}
89impl<'a> From<&'a DocumentElementURI> for URIRef<'a> {
90    #[inline]
91    fn from(value: &'a DocumentElementURI) -> Self {
92        URIRef::Narrative(NarrativeURIRef::Element(value))
93    }
94}
95impl<'a> URIRefTrait<'a> for &'a DocumentElementURI {
96    type Owned = DocumentElementURI;
97    #[inline]
98    fn owned(self) -> DocumentElementURI {
99        self.clone()
100    }
101}
102
103
104impl DocumentElementURI {
105    pub(super) fn pre_parse<R>(
106        s: &str,
107        uri_kind: &'static str,
108        f: impl FnOnce(Self, Split<char>) -> Result<R, URIParseError>,
109    ) -> Result<R, URIParseError> {
110        DocumentURI::pre_parse(s, uri_kind, |document, mut split| {
111            let Some(s) = split.next() else {
112                return Err(URIParseError::MissingPartFor {
113                    uri_kind,
114                    part: "narrative element name",
115                    original: s.to_string(),
116                });
117            };
118            s.strip_prefix(concatcp!(DocumentElementURI::SEPARATOR, "="))
119                .map_or_else(
120                    || {
121                        Err(URIParseError::MissingPartFor {
122                            uri_kind,
123                            part: "narrative element name",
124                            original: s.to_string(),
125                        })
126                    },
127                    |name| {
128                        f(
129                            Self {
130                                document,
131                                name: name.parse()?,
132                            },
133                            split,
134                        )
135                    },
136                )
137        })
138    }
139}
140
141impl FromStr for DocumentElementURI {
142    type Err = URIParseError;
143    fn from_str(s: &str) -> Result<Self, Self::Err> {
144        Self::pre_parse(s, "document element uri", |u, mut split| {
145            if split.next().is_some() {
146                return Err(URIParseError::TooManyPartsFor {
147                    uri_kind: "document element uri",
148                    original: s.to_string(),
149                });
150            }
151            Ok(u)
152        })
153    }
154}
155
156impl ArchiveURITrait for DocumentElementURI {
157    #[inline]
158    fn archive_uri(&self) -> ArchiveURIRef {
159        self.document.archive_uri()
160    }
161}
162impl PathURITrait for DocumentElementURI {
163    #[inline]
164    fn as_path(&self) -> PathURIRef {
165        self.document.as_path()
166    }
167    #[inline]
168    fn path(&self) -> Option<&Name> {
169        self.document.path()
170    }
171}
172
173#[cfg(feature = "serde")]
174mod serde_impl {
175    use crate::uris::{serialize, DocumentElementURI};
176    serialize!(DE DocumentElementURI);
177}
178
179#[cfg(feature="tantivy")]
180impl tantivy::schema::document::ValueDeserialize for DocumentElementURI {
181    fn deserialize<'de, D>(deserializer: D) -> Result<Self, tantivy::schema::document::DeserializeError>
182        where D: tantivy::schema::document::ValueDeserializer<'de> {
183        deserializer.deserialize_string()?.parse()
184          .map_err(|_| tantivy::schema::document::DeserializeError::custom(""))
185    }
186  }