Skip to main content

rdf_syntax/id/
mod.rs

1use core::fmt;
2use std::borrow::Cow;
3use std::cmp::Ordering;
4use std::str::FromStr;
5
6use crate::{BlankId, BlankIdBuf, RdfDisplay};
7use iref::{InvalidIri, Iri, IriBuf};
8
9mod r#ref;
10pub use r#ref::*;
11
12mod cow;
13pub use cow::*;
14
15/// Resource identifier.
16///
17/// Lexical identifier of an RDF resource, either an IRI or a blank node
18/// identifier.
19#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21#[cfg_attr(feature = "serde", serde(untagged))]
22pub enum Id {
23	/// Blank node identifier.
24	BlankId(BlankIdBuf),
25
26	/// IRI.
27	Iri(IriBuf),
28}
29
30impl Id {
31	/// Checks if this is a blank node identifier.
32	pub fn is_blank_id(&self) -> bool {
33		matches!(self, Self::BlankId(_))
34	}
35
36	/// Returns this identifier as a blank node identifier, if it is one.
37	pub fn as_blank_id(&self) -> Option<&BlankId> {
38		match self {
39			Self::BlankId(b) => Some(b),
40			_ => None,
41		}
42	}
43
44	/// Checks if this is an IRI.
45	pub fn is_iri(&self) -> bool {
46		matches!(self, Self::Iri(_))
47	}
48
49	/// Returns this identifier as an IRI, if it is one.
50	pub fn as_iri(&self) -> Option<&Iri> {
51		match self {
52			Self::Iri(iri) => Some(iri),
53			_ => None,
54		}
55	}
56
57	/// Returns a reference to this identifier.
58	pub fn as_ref(&self) -> IdRef<'_> {
59		match self {
60			Self::BlankId(blank_id) => IdRef::BlankId(blank_id),
61			Self::Iri(iri) => IdRef::Iri(iri),
62		}
63	}
64
65	/// Turns this identifier into a blank node identifier, if it is one.
66	pub fn into_blank_id(self) -> Option<BlankIdBuf> {
67		match self {
68			Self::BlankId(b) => Some(b),
69			_ => None,
70		}
71	}
72
73	/// Turns this identifier into an IRI, if it is one.
74	pub fn into_iri(self) -> Option<IriBuf> {
75		match self {
76			Self::Iri(iri) => Some(iri),
77			_ => None,
78		}
79	}
80
81	/// Returns a copy-on-write reference to this identifier.
82	pub fn as_cow(&self) -> CowId<'_> {
83		match self {
84			Self::BlankId(blank_id) => CowId::BlankId(Cow::Borrowed(blank_id)),
85			Self::Iri(iri) => CowId::Iri(Cow::Borrowed(iri)),
86		}
87	}
88
89	/// Turns this identifier into a copy-on-write identifier.
90	pub fn into_cow(self) -> CowId<'static> {
91		match self {
92			Self::BlankId(blank_id) => CowId::BlankId(Cow::Owned(blank_id)),
93			Self::Iri(iri) => CowId::Iri(Cow::Owned(iri)),
94		}
95	}
96}
97
98impl FromStr for Id {
99	type Err = InvalidIri<String>;
100
101	fn from_str(s: &str) -> Result<Self, Self::Err> {
102		match BlankIdBuf::from_str(s) {
103			Ok(b) => Ok(Self::BlankId(b)),
104			Err(_) => IriBuf::from_str(s).map(Self::Iri),
105		}
106	}
107}
108
109impl AsRef<str> for Id {
110	fn as_ref(&self) -> &str {
111		match self {
112			Self::BlankId(b) => b.as_ref(),
113			Self::Iri(i) => i.as_ref(),
114		}
115	}
116}
117
118impl fmt::Display for Id {
119	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120		match self {
121			Self::BlankId(b) => b.fmt(f),
122			Self::Iri(i) => i.fmt(f),
123		}
124	}
125}
126
127impl RdfDisplay for Id {
128	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129		match self {
130			Self::BlankId(b) => b.rdf_fmt(f),
131			Self::Iri(i) => i.rdf_fmt(f),
132		}
133	}
134}
135
136impl PartialEq<Iri> for Id {
137	fn eq(&self, other: &Iri) -> bool {
138		match self {
139			Self::Iri(iri) => iri.as_iri() == other,
140			_ => false,
141		}
142	}
143}
144
145impl PartialEq<&Iri> for Id {
146	fn eq(&self, other: &&Iri) -> bool {
147		self.eq(*other)
148	}
149}
150
151impl PartialEq<IriBuf> for Id {
152	fn eq(&self, other: &IriBuf) -> bool {
153		match self {
154			Self::Iri(iri) => iri == other,
155			_ => false,
156		}
157	}
158}
159
160impl PartialEq<&IriBuf> for Id {
161	fn eq(&self, other: &&IriBuf) -> bool {
162		self.eq(*other)
163	}
164}
165
166impl PartialEq<BlankId> for Id {
167	fn eq(&self, other: &BlankId) -> bool {
168		match self {
169			Self::BlankId(b) => b.as_blank_id() == other,
170			_ => false,
171		}
172	}
173}
174
175impl PartialEq<BlankIdBuf> for Id {
176	fn eq(&self, other: &BlankIdBuf) -> bool {
177		match self {
178			Self::BlankId(b) => b == other,
179			_ => false,
180		}
181	}
182}
183
184impl PartialEq<&BlankId> for Id {
185	fn eq(&self, other: &&BlankId) -> bool {
186		self.eq(*other)
187	}
188}
189
190impl PartialEq<&BlankIdBuf> for Id {
191	fn eq(&self, other: &&BlankIdBuf) -> bool {
192		self.eq(*other)
193	}
194}
195
196impl<'a> PartialEq<IdRef<'a>> for Id {
197	fn eq(&self, other: &IdRef<'a>) -> bool {
198		match (self, other) {
199			(Self::BlankId(a), IdRef::BlankId(b)) => a == *b,
200			(Self::Iri(a), IdRef::Iri(b)) => a == *b,
201			_ => false,
202		}
203	}
204}
205
206impl<'a> PartialOrd<IdRef<'a>> for Id {
207	fn partial_cmp(&self, other: &IdRef<'a>) -> Option<Ordering> {
208		match (self, other) {
209			(Self::BlankId(a), IdRef::BlankId(b)) => a.as_blank_id().partial_cmp(*b),
210			(Self::BlankId(_), IdRef::Iri(_)) => Some(Ordering::Less),
211			(Self::Iri(_), IdRef::BlankId(_)) => Some(Ordering::Greater),
212			(Self::Iri(a), IdRef::Iri(b)) => a.as_iri().partial_cmp(b),
213		}
214	}
215}