Skip to main content

mbed_core/
lib.rs

1use std::{borrow::Cow::Borrowed, fs::File, ops::Deref};
2
3use mbed_macros::{Artifact, LocalFile, Writer};
4use tanager::Parse;
5
6#[proc_macro]
7pub fn include_bytes(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
8    #[derive(Debug, Hash, Parse)]
9    #[tanager(transparent)]
10    struct Input(Files);
11
12    impl std::fmt::Display for Input {
13        #[inline]
14        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15            write!(f, "mbed::include_bytes {}", self.0)
16        }
17    }
18
19    mbed_macros::execute_fn(item.into(), |deps, input: Input| {
20        deps.track_files(&*input.0);
21
22        let mut writer = Writer::new()?;
23
24        for path in input.0.iter() {
25            std::io::copy(&mut File::open(path)?, &mut writer)?;
26        }
27
28        std::io::Result::Ok(Artifact {
29            mime: input
30                .0
31                .first()
32                .map(|x| {
33                    mime_guess::from_path(x)
34                        .first_or_octet_stream()
35                        .to_string()
36                        .into()
37                })
38                .unwrap_or(Borrowed("application/octet-stream")),
39
40            ..writer.finish()?
41        })
42    })
43    .into()
44}
45
46#[proc_macro]
47pub fn include_str(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
48    #[derive(Debug, Hash, Parse)]
49    #[tanager(transparent)]
50    struct Input(Files);
51
52    impl std::fmt::Display for Input {
53        #[inline]
54        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55            write!(f, "mbed::include_str {}", self.0)
56        }
57    }
58
59    mbed_macros::execute_fn(item.into(), |deps, input: Input| {
60        deps.track_files(&*input.0);
61
62        let mut writer = Writer::new()?;
63
64        for path in input.0.iter() {
65            std::io::copy(&mut File::open(path)?, &mut writer)?;
66        }
67
68        std::io::Result::Ok(Artifact {
69            mime: input
70                .0
71                .first()
72                .map(|x| {
73                    mime_guess::from_path(x)
74                        .first_or_text_plain()
75                        .to_string()
76                        .into()
77                })
78                .unwrap_or(Borrowed("text/plain")),
79
80            ..writer.finish()?.into_text_artifact()
81        })
82    })
83    .into()
84}
85
86#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Parse)]
87#[tanager(transparent)]
88struct Files(Box<[LocalFile]>);
89
90impl std::fmt::Display for Files {
91    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92        let cwd = std::env::current_dir().ok();
93
94        let paths = self
95            .0
96            .iter()
97            .map(|x| {
98                cwd.as_ref()
99                    .and_then(|cwd| x.strip_prefix(cwd).ok())
100                    .unwrap_or(x.as_path())
101            })
102            .map(|x| x.to_string_lossy());
103
104        write!(f, "[ ")?;
105
106        let mut b: usize = 80;
107
108        for (index, path) in paths.enumerate() {
109            if index != 0 {
110                write!(f, ", ")?;
111
112                b = b.saturating_sub(path.len());
113
114                if b != 0 {
115                    write!(f, "{path}")?;
116                } else {
117                    write!(f, "...")?;
118                }
119            } else {
120                b = b.saturating_sub(path.len());
121
122                write!(f, "{path}")?;
123            }
124        }
125
126        write!(f, " ]")?;
127
128        Ok(())
129    }
130}
131
132impl Deref for Files {
133    type Target = [LocalFile];
134
135    #[inline]
136    fn deref(&self) -> &Self::Target {
137        &self.0
138    }
139}