Skip to main content

rdf_syntax/
display.rs

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