mod_mimepart/
builder.rs

1use crate::PartRef;
2use config::{SerdeWrappedValue, any_err};
3use mailparsing::{AttachmentOptions, MessageBuilder};
4use mlua::{UserData, UserDataMethods, UserDataRef};
5use parking_lot::Mutex;
6use std::sync::Arc;
7
8#[derive(Clone)]
9pub struct Builder {
10    builder: Arc<Mutex<Option<MessageBuilder<'static>>>>,
11}
12
13impl Builder {
14    pub fn new() -> Self {
15        Self {
16            builder: Arc::new(Mutex::new(Some(MessageBuilder::new()))),
17        }
18    }
19
20    pub fn mutate<F: FnOnce(&mut MessageBuilder) -> anyhow::Result<R>, R>(
21        &self,
22        f: F,
23    ) -> anyhow::Result<R> {
24        let mut builder = self.builder.lock();
25        match builder.as_mut() {
26            Some(builder) => (f)(builder),
27            None => anyhow::bail!("builder already built!"),
28        }
29    }
30
31    pub fn take(&self) -> anyhow::Result<MessageBuilder<'static>> {
32        match self.builder.lock().take() {
33            Some(builder) => Ok(builder),
34            None => anyhow::bail!("builder already built!"),
35        }
36    }
37}
38
39impl UserData for Builder {
40    fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
41        methods.add_method("set_stable_content", |_lua, this, stable: bool| {
42            this.mutate(|builder| {
43                builder.set_stable_content(stable);
44                Ok(())
45            })
46            .map_err(any_err)
47        });
48        methods.add_method("text_plain", |_lua, this, text: String| {
49            this.mutate(|builder| {
50                builder.text_plain(&text);
51                Ok(())
52            })
53            .map_err(any_err)
54        });
55        methods.add_method("text_html", |_lua, this, text: String| {
56            this.mutate(|builder| {
57                builder.text_html(&text);
58                Ok(())
59            })
60            .map_err(any_err)
61        });
62        methods.add_method(
63            "attach",
64            |_lua,
65             this,
66             (content_type, data, opts): (
67                String,
68                mlua::String,
69                Option<SerdeWrappedValue<AttachmentOptions>>,
70            )| {
71                this.mutate(|builder| {
72                    builder.attach(&content_type, &data.as_bytes(), opts.as_deref())?;
73                    Ok(())
74                })
75                .map_err(any_err)
76            },
77        );
78        methods.add_method("attach_part", |_lua, this, part: UserDataRef<PartRef>| {
79            let part = part.resolve().map_err(any_err)?.to_owned();
80            this.mutate(|builder| {
81                builder.attach_part(part);
82                Ok(())
83            })
84            .map_err(any_err)
85        });
86        methods.add_method("build", |_lua, this, ()| {
87            let part = this.take().map_err(any_err)?.build().map_err(any_err)?;
88            Ok(PartRef::new(part))
89        });
90    }
91}