dejavu_runtime/display/
mod.rs1use core::fmt::{Display, Formatter, Write};
2
3pub trait Escaper {
4 fn write_escaped<W>(&self, fmt: W, string: &str) -> core::fmt::Result
5 where
6 W: Write;
7}
8
9#[derive(Debug)]
10pub struct EscapeDisplay<E, T>
11where
12 E: Escaper,
13 T: Display,
14{
15 value: DisplayValue<T>,
16 escaper: E,
17}
18
19#[derive(Debug)]
20pub struct EscapeWriter<'a, E, W> {
21 fmt: W,
22 escaper: &'a E,
23}
24
25#[derive(Debug)]
26pub struct Escaped<'a, E>
27where
28 E: Escaper,
29{
30 string: &'a str,
31 escaper: E,
32}
33
34impl<E, T> EscapeDisplay<E, T>
35where
36 E: Escaper,
37 T: Display,
38{
39 pub fn dangerous(value: T, escaper: E) -> Self {
40 Self { value: DisplayValue::Unsafe(value), escaper }
41 }
42
43 pub fn safe(value: T, escaper: E) -> Self {
44 Self { value: DisplayValue::Safe(value), escaper }
45 }
46
47 #[must_use]
48 pub fn mark_safe(mut self) -> EscapeDisplay<E, T> {
49 self.value = match self.value {
50 DisplayValue::Unsafe(t) => DisplayValue::Safe(t),
51 _ => self.value,
52 };
53 self
54 }
55}
56
57impl<E, T> Display for EscapeDisplay<E, T>
58where
59 E: Escaper,
60 T: Display,
61{
62 fn fmt(&self, fmt: &mut Formatter<'_>) -> core::fmt::Result {
63 match self.value {
64 DisplayValue::Unsafe(ref t) => write!(EscapeWriter { fmt, escaper: &self.escaper }, "{t}"),
65 DisplayValue::Safe(ref t) => t.fmt(fmt),
66 }
67 }
68}
69
70impl<E, W> Write for EscapeWriter<'_, E, W>
71where
72 W: Write,
73 E: Escaper,
74{
75 fn write_str(&mut self, s: &str) -> core::fmt::Result {
76 self.escaper.write_escaped(&mut self.fmt, s)
77 }
78}
79
80pub fn escape<E>(string: &str, escaper: E) -> Escaped<'_, E>
81where
82 E: Escaper,
83{
84 Escaped { string, escaper }
85}
86
87impl<E> Display for Escaped<'_, E>
88where
89 E: Escaper,
90{
91 fn fmt(&self, fmt: &mut Formatter<'_>) -> core::fmt::Result {
92 self.escaper.write_escaped(fmt, self.string)
93 }
94}
95
96#[derive(Debug, PartialEq)]
97enum DisplayValue<T>
98where
99 T: Display,
100{
101 Safe(T),
102 Unsafe(T),
103}