rdf_types/
display.rs

1use std::fmt;
2
3use langtag::{LangTag, LangTagBuf};
4
5/// Display method for RDF syntax elements.
6pub trait RdfDisplay {
7	/// Formats the value using the given formatter.
8	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
9
10	/// Prepare the value to be formatted as an RDF syntax element.
11	#[inline(always)]
12	fn rdf_display(&self) -> RdfDisplayed<&Self> {
13		RdfDisplayed(self)
14	}
15}
16
17impl RdfDisplay for str {
18	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
19		use fmt::Display;
20		write!(f, "\"")?;
21
22		for c in self.chars() {
23			match c {
24				'"' => write!(f, "\\\""),
25				'\\' => write!(f, "\\\\"),
26				'\n' => write!(f, "\\n"),
27				'\r' => write!(f, "\\r"),
28				c => c.fmt(f),
29			}?
30		}
31
32		write!(f, "\"")
33	}
34}
35
36impl RdfDisplay for String {
37	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38		self.as_str().rdf_fmt(f)
39	}
40}
41
42impl RdfDisplay for iref::IriRef {
43	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44		write!(f, "<")?;
45
46		for c in self.as_str().chars() {
47			match c {
48				'\x00'..='\x20' | '<' | '>' | '"' | '{' | '}' | '|' | '^' | '`' | '\\' => {
49					let bytes: u32 = c.into();
50					write!(f, "\\u{bytes:#04x}")
51				}
52				_ => fmt::Display::fmt(&c, f),
53			}?;
54		}
55
56		write!(f, ">")
57	}
58}
59
60impl RdfDisplay for iref::Iri {
61	#[inline(always)]
62	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63		self.as_iri_ref().rdf_fmt(f)
64	}
65}
66
67#[cfg(feature = "contextual")]
68impl<C: ?Sized> RdfDisplayWithContext<C> for iref::Iri {
69	fn rdf_fmt_with(&self, _context: &C, f: &mut fmt::Formatter) -> fmt::Result {
70		self.rdf_fmt(f)
71	}
72}
73
74impl RdfDisplay for iref::IriBuf {
75	#[inline(always)]
76	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77		self.as_iri_ref().rdf_fmt(f)
78	}
79}
80
81#[cfg(feature = "contextual")]
82impl<C: ?Sized> RdfDisplayWithContext<C> for iref::IriBuf {
83	fn rdf_fmt_with(&self, _context: &C, f: &mut fmt::Formatter) -> fmt::Result {
84		self.rdf_fmt(f)
85	}
86}
87
88impl RdfDisplay for iref::IriRefBuf {
89	#[inline(always)]
90	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91		self.as_iri_ref().rdf_fmt(f)
92	}
93}
94
95#[cfg(feature = "contextual")]
96impl<C: ?Sized> RdfDisplayWithContext<C> for iref::IriRefBuf {
97	fn rdf_fmt_with(&self, _context: &C, f: &mut fmt::Formatter) -> fmt::Result {
98		self.rdf_fmt(f)
99	}
100}
101
102impl RdfDisplay for LangTag {
103	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104		use fmt::Display;
105		self.as_str().fmt(f)
106	}
107}
108
109#[cfg(feature = "contextual")]
110impl<C: ?Sized> RdfDisplayWithContext<C> for LangTag {
111	fn rdf_fmt_with(&self, _context: &C, f: &mut fmt::Formatter) -> fmt::Result {
112		self.rdf_fmt(f)
113	}
114}
115
116impl RdfDisplay for LangTagBuf {
117	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118		use fmt::Display;
119		self.as_str().fmt(f)
120	}
121}
122
123#[cfg(feature = "contextual")]
124impl<C: ?Sized> RdfDisplayWithContext<C> for LangTagBuf {
125	fn rdf_fmt_with(&self, _context: &C, f: &mut fmt::Formatter) -> fmt::Result {
126		self.rdf_fmt(f)
127	}
128}
129
130impl<T: RdfDisplay + ?Sized> RdfDisplay for &T {
131	#[inline(always)]
132	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
133		T::rdf_fmt(*self, f)
134	}
135}
136
137/// Value ready to be formatted as an RDF syntax element.
138pub struct RdfDisplayed<T>(T);
139
140impl<T: RdfDisplay> fmt::Display for RdfDisplayed<T> {
141	#[inline(always)]
142	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143		self.0.rdf_fmt(f)
144	}
145}
146
147#[cfg(feature = "contextual")]
148pub trait RdfDisplayWithContext<C: ?Sized> {
149	fn rdf_fmt_with(&self, context: &C, f: &mut fmt::Formatter) -> fmt::Result;
150}
151
152#[cfg(feature = "contextual")]
153impl<'a, T: RdfDisplayWithContext<C> + ?Sized, C: ?Sized> RdfDisplayWithContext<C> for &'a T {
154	#[inline(always)]
155	fn rdf_fmt_with(&self, context: &C, f: &mut fmt::Formatter) -> fmt::Result {
156		T::rdf_fmt_with(*self, context, f)
157	}
158}
159
160#[cfg(feature = "contextual")]
161impl<'c, T: RdfDisplayWithContext<C>, C: ?Sized> RdfDisplay for contextual::Contextual<T, &'c C> {
162	#[inline(always)]
163	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164		self.0.rdf_fmt_with(self.1, f)
165	}
166}
167
168#[cfg(feature = "contextual")]
169impl<'c, T: RdfDisplayWithContext<C>, C: ?Sized> RdfDisplay
170	for contextual::Contextual<T, &'c mut C>
171{
172	#[inline(always)]
173	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
174		self.0.rdf_fmt_with(self.1, f)
175	}
176}