1use std::fmt;
2
3use langtag::{LangTag, LangTagBuf};
4
5pub trait RdfDisplay {
7 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
9
10 #[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
137pub 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}