yarte_helpers/helpers/
markup.rs

1// Based on https://github.com/utkarshkukreti/markup.rs/blob/master/markup/src/lib.rs
2use std::fmt::{self, Display};
3
4use v_htmlescape::escape;
5
6/// Render trait, used for wrap unsafe expressions `{{ ... }}` when it's in a html template
7pub trait Render {
8    fn render(&self, f: &mut fmt::Formatter) -> fmt::Result;
9}
10
11/// Auto ref trait
12pub trait RenderA {
13    /// Render in buffer will html escape the string type
14    ///
15    /// # Safety
16    /// Possible overlap if you have a chance to implement:
17    /// have a buffer reference in your data type
18    fn __renders_it(&self, buf: &mut fmt::Formatter) -> fmt::Result;
19}
20
21impl<T: Render + ?Sized> RenderA for T {
22    #[inline(always)]
23    fn __renders_it(&self, buf: &mut fmt::Formatter) -> fmt::Result {
24        Render::render(self, buf)
25    }
26}
27impl Render for str {
28    #[inline(always)]
29    fn render(&self, f: &mut fmt::Formatter) -> fmt::Result {
30        escape(self).fmt(f)
31    }
32}
33
34impl Render for String {
35    #[inline(always)]
36    fn render(&self, f: &mut fmt::Formatter) -> fmt::Result {
37        escape(self.as_str()).fmt(f)
38    }
39}
40
41macro_rules! itoa_display {
42    ($($ty:ty)*) => {
43        $(
44            impl Render for $ty {
45                #[inline(always)]
46                fn render(&self, f: &mut fmt::Formatter) -> fmt::Result {
47                    f.write_str(itoa::Buffer::new().format(*self))
48                    .map(|_| ())
49                    .map_err(|_| fmt::Error)
50                }
51            }
52        )*
53    };
54}
55
56#[rustfmt::skip]
57itoa_display! {
58    u8 u16 u32 u64 u128 usize
59    i8 i16 i32 i64 i128 isize
60}
61
62macro_rules! dtoa_display {
63    ($($ty:ty)*) => {
64        $(
65            impl Render for $ty {
66                #[inline(always)]
67                fn render(&self, f: &mut fmt::Formatter) -> fmt::Result {
68                    f.write_str(dtoa::Buffer::new().format(*self))
69                    .map(|_| ())
70                    .map_err(|_| fmt::Error)
71                }
72            }
73        )*
74    };
75}
76
77#[rustfmt::skip]
78dtoa_display! {
79    f32 f64
80}
81
82// TODO: in the future, your future.
83impl Render for char {
84    #[inline(always)]
85    fn render(&self, f: &mut fmt::Formatter) -> fmt::Result {
86        escape(&self.to_string()).fmt(f)
87    }
88}
89
90macro_rules! raw_display {
91    ($($ty:ty)*) => {
92        $(
93            impl Render for $ty {
94                #[inline(always)]
95                fn render(&self, f: &mut fmt::Formatter) -> fmt::Result {
96                    self.fmt(f)
97                }
98            }
99        )*
100    };
101}
102
103#[rustfmt::skip]
104raw_display! {
105    bool
106}
107
108#[cfg(feature = "json")]
109mod json {
110    use super::*;
111    use crate::at_helpers::{Json, JsonPretty};
112    use crate::helpers::io_fmt::IoFmt;
113    use serde::Serialize;
114    use serde_json::{to_writer, to_writer_pretty};
115
116    impl<'a, S: Serialize> Render for Json<'a, S> {
117        #[inline(always)]
118        fn render(&self, f: &mut fmt::Formatter) -> fmt::Result {
119            to_writer(IoFmt::new(f), self.0).map_err(|_| fmt::Error)
120        }
121    }
122
123    impl<'a, D: Serialize> Render for JsonPretty<'a, D> {
124        #[inline(always)]
125        fn render(&self, f: &mut fmt::Formatter) -> fmt::Result {
126            to_writer_pretty(IoFmt::new(f), self.0).map_err(|_| fmt::Error)
127        }
128    }
129}