catalyzer/internals/
content_loader.rs

1//! Content loaders for strings and bytes.
2
3use axum::body::Body;
4use std::path::Path;
5use crate::Result;
6use core::fmt;
7use utils::*;
8
9macro_rules! loader {
10    ($(
11        $(#[$attr:meta])*
12        $name:ident -> $inner:ident(
13            $(#[$alloc_attr:meta])*;$(#[$alloc_fn_attr:meta])*$alloc:ty;
14            $(#[$static_attr:meta])*;$(#[$static_fn_attr:meta])*$static:ty;
15        )
16    )+) => ($(
17        $(#[$attr])*
18        #[repr(transparent)]
19        #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
20        pub struct $name($inner::$name);
21        impl fmt::Debug for $name {
22            #[inline]
23            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24                self.0.fmt(f)
25            }
26        }
27        impl From<$alloc> for $name {
28            #[inline]
29            fn from(s: $alloc) -> Self {
30                Self($inner::$name::Alloc(s))
31            }
32        }
33        impl From<$static> for $name {
34            #[inline]
35            fn from(s: $static) -> Self {
36                Self($inner::$name::Static(s))
37            }
38        }
39        impl From<$name> for Body {
40            #[inline]
41            fn from(this: $name) -> Self {
42                Body::from(this.0)
43            }
44        }
45        impl $name {
46            $(#[$alloc_fn_attr])*
47            #[inline]
48            pub const fn new_static(s: $static) -> Self {
49                Self($inner::$name::Static(s))
50            }
51            $(#[$static_fn_attr])*
52            #[inline]
53            pub fn new_alloc(s: $alloc) -> Self {
54                Self($inner::$name::Alloc(s))
55            }
56        }
57        mod $inner {
58            use super::*;
59            #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
60            pub(crate) enum $name {
61                $(#[$alloc_attr])*
62                Alloc($alloc),
63                $(#[$static_attr])*
64                Static($static),
65            }
66            impl From<$name> for Body {
67                #[inline]
68                fn from(this: $name) -> Self {
69                    match this {
70                        $name::Alloc(s) => Body::from(s),
71                        $name::Static(s) => Body::from(s),
72                    }
73                }
74            }
75        }
76    )+);
77}
78
79loader!(
80    /// A content loader for valid UTF-8 strings.
81    StringContentLoader -> string_inner(/// An allocated String.
82        ;/// Creates a new `StringContentLoader` from an allocated `String`.
83        String;
84        /// A static string.
85        ;/// Creates a new `StringContentLoader` from a static string.
86        &'static str;
87    )
88    /// A content loader for bytes.
89    BytesContentLoader -> bytes_inner(/// An allocated Vec<u8>.
90        ;/// Creates a new `BytesContentLoader` from an allocated `Vec<u8>`.
91        Vec<u8>;
92        /// A static byte slice.
93        ;/// Creates a new `BytesContentLoader` from a static byte slice.
94        &'static [u8];
95    )
96);
97
98impl StringContentLoader {
99    /// Creates a new `StringContentLoader` from a file.
100    pub async fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
101        tokio::fs::read_to_string(path).await.map_auto()
102    }
103}
104
105impl BytesContentLoader {
106    /// Creates a new `BytesContentLoader` from a file.
107    pub async fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
108        tokio::fs::read(path).await.map_auto()
109    }
110}
111
112impl fmt::Display for StringContentLoader {
113    #[inline]
114    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115        match &self.0 {
116            string_inner::StringContentLoader::Alloc(s) => s.fmt(f),
117            string_inner::StringContentLoader::Static(s) => s.fmt(f),
118        }
119    }
120}
121
122impl fmt::Display for BytesContentLoader {
123    #[inline]
124    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
125        match &self.0 {
126            bytes_inner::BytesContentLoader::Alloc(s) => String::from_utf8_lossy(s).fmt(f),
127            bytes_inner::BytesContentLoader::Static(s) => String::from_utf8_lossy(s).fmt(f),
128        }
129    }
130}