1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use crate::{builder::metadata::BODY_META, *};
use anyhow::{anyhow, Context as _};
use std::fs::copy;
use std::io::Write;

/// [`FileReader`] compiler will read source file as String and
/// store data as `_body` metadata.
pub struct FileReader;
impl FileReader {
    pub fn new() -> Self {
        Self
    }
}
impl Compiler for FileReader {
    fn compile(&self, ctx: Context) -> CompilerReturn {
        compile!({
            let mut ctx = ctx;
            let src = ctx.get_source_data()?;
            ctx.insert_compiling_raw_metadata(BODY_META, src)?;
            Ok(ctx)
        })
    }
}

/// [`FileWriter`] compiler will write data stored in `_body` metadata to target file.
pub struct FileWriter;
impl FileWriter {
    pub fn new() -> Self {
        Self
    }
}
impl Compiler for FileWriter {
    fn compile(&self, ctx: Context) -> CompilerReturn {
        compile!({
            let target_display = ctx.target()?;
            let target_display = target_display.display();
            let mut target = ctx
                .open_target()
                .with_context(|| format!("Failed to open file {}", target_display))?;
            let body = ctx.body()?;
            if let Some(s) = body.as_str() {
                target
                    .write(s.as_bytes())
                    .with_context(|| format!("Failed to write file {}", target_display))?;
            } else if body.is_array() {
                let bytes = body.as_bytes()?;
                target
                    .write(&bytes)
                    .with_context(|| format!("Failed to write file {}", target_display))?;
            } else {
                return Err(anyhow!("Invalid body format"));
            }
            Ok(ctx)
        })
    }
}

/// [`CopyCompiler`] will simply copies source file to target file
pub struct CopyCompiler;
impl CopyCompiler {
    pub fn new() -> Self {
        Self
    }
}
impl Compiler for CopyCompiler {
    fn compile(&self, ctx: Context) -> CompilerReturn {
        compile!({
            ctx.create_target_parent_dir()?;
            let src = ctx.source()?;
            let tgt = ctx.target()?;
            copy(src, tgt).context("Copy error")?;
            Ok(ctx)
        })
    }
}