darklua_core/frontend/
mod.rs

1mod configuration;
2mod error;
3mod options;
4mod process_result;
5mod resources;
6mod utils;
7mod work_cache;
8mod work_item;
9mod worker;
10
11use std::path::Path;
12
13#[allow(unused_imports)]
14pub use configuration::{Configuration, GeneratorParameters, BundleConfiguration};
15pub use error::{DarkluaError, DarkluaResult};
16pub use options::Options;
17pub use process_result::ProcessResult;
18pub use resources::Resources;
19use serde::Serialize;
20use work_item::WorkItem;
21use worker::Worker;
22
23use crate::{
24    generator::{DenseLuaGenerator, LuaGenerator},
25    nodes::{Block, ReturnStatement},
26    process::to_expression,
27    utils::normalize_path,
28};
29
30pub fn process(resources: &Resources, options: Options) -> ProcessResult {
31    match private_process(resources, options) {
32        Ok(result) | Err(result) => result,
33    }
34}
35
36/// Convert serializable data into a Lua module
37pub fn convert_data(value: impl Serialize) -> Result<String, DarkluaError> {
38    let expression = to_expression(&value).map_err(DarkluaError::from)?;
39
40    let block = Block::default()
41        .with_last_statement(ReturnStatement::default().with_expression(expression));
42
43    let mut generator = DenseLuaGenerator::default();
44    generator.write_block(&block);
45    Ok(generator.into_string())
46}
47
48fn private_process(
49    resources: &Resources,
50    options: Options,
51) -> Result<ProcessResult, ProcessResult> {
52    let worker = Worker::new(resources);
53
54    if let Some(output) = options.output().map(Path::to_path_buf) {
55        if resources.is_file(options.input())? {
56            if resources.is_directory(&output)? {
57                let file_name = options.input().file_name().ok_or_else(|| {
58                    DarkluaError::custom(format!(
59                        "unable to extract file name from `{}`",
60                        options.input().display()
61                    ))
62                })?;
63
64                worker.process(
65                    once_ok(WorkItem::new(options.input(), output.join(file_name))),
66                    options,
67                )
68            } else if resources.is_file(&output)? || output.extension().is_some() {
69                worker.process(once_ok(WorkItem::new(options.input(), output)), options)
70            } else {
71                let file_name = options.input().file_name().ok_or_else(|| {
72                    DarkluaError::custom(format!(
73                        "unable to extract file name from `{}`",
74                        options.input().display()
75                    ))
76                })?;
77
78                worker.process(
79                    once_ok(WorkItem::new(options.input(), output.join(file_name))),
80                    options,
81                )
82            }
83        } else {
84            let input = options.input().to_path_buf();
85
86            worker.process(
87                resources.collect_work(&input).map(|source| {
88                    let source = normalize_path(source);
89                    source
90                        .strip_prefix(&input)
91                        .map(|relative| WorkItem::new(&source, output.join(relative)))
92                        .map_err(|err| {
93                            DarkluaError::custom(format!(
94                                "unable to remove path prefix `{}` from `{}`: {}",
95                                input.display(),
96                                source.display(),
97                                err
98                            ))
99                        })
100                }),
101                options,
102            )
103        }
104    } else {
105        let input = options.input().to_path_buf();
106        worker.process(
107            resources
108                .collect_work(input)
109                .map(|source| Ok(WorkItem::new_in_place(source))),
110            options,
111        )
112    }
113}
114
115#[inline]
116fn once_ok<T, E>(value: T) -> impl Iterator<Item = Result<T, E>> {
117    std::iter::once(Ok(value))
118}