1
use core::fmt;
2
use std::borrow::Cow;
3
use std::path::PathBuf;
4

            
5
use crate::domain::commands::arguments::Argument;
6
use color_eyre::{eyre::Context, Result};
7
use serde::{Deserialize, Serialize};
8
use transient::Transient;
9

            
10
use crate::domain::translation_unit::TranslationUnit;
11
use crate::impl_translation_unit_for;
12

            
13
36
#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize, Transient)]
14
pub struct SourceFile<'a> {
15
14
    pub path: PathBuf,
16
14
    pub file_stem: Cow<'a, str>,
17
14
    pub extension: Cow<'a, str>,
18
}
19

            
20
impl_translation_unit_for!(SourceFile<'a>);
21

            
22
impl<'a> fmt::Display for SourceFile<'a> {
23
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24
        write!(
25
            f,
26
            "({:?}/{:?}.{:?})",
27
            self.path, self.file_stem, self.extension
28
        )
29
    }
30
}
31

            
32
#[derive(Debug, PartialEq, Eq)]
33
pub enum Source {
34
    File(PathBuf),
35
    Glob(GlobPattern),
36
}
37

            
38
impl Source {
39
    #[inline(always)]
40
14
    pub fn paths(&self) -> Result<Vec<PathBuf>> {
41
14
        match self {
42
2
            Source::File(file) => Ok(vec![file.to_path_buf()]),
43
12
            Source::Glob(pattern) => pattern.resolve(),
44
        }
45
14
    }
46
}
47

            
48
#[derive(Debug, PartialEq, Eq)]
49
pub struct GlobPattern(pub PathBuf);
50

            
51
impl GlobPattern {
52
    #[inline(always)]
53
12
    fn resolve(&self) -> Result<Vec<PathBuf>> {
54
12
        glob::glob(self.0.to_str().unwrap_or_default())?
55
4
            .map(|path| path.with_context(|| ""))
56
            .collect()
57
12
    }
58
}
59

            
60
8
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, Clone)]
61
2
pub struct SourceSet<'a>(Vec<SourceFile<'a>>);
62

            
63
impl<'a> SourceSet<'a> {
64
16
    pub fn new(sources: Vec<SourceFile<'a>>) -> Self {
65
16
        Self(sources)
66
16
    }
67

            
68
4
    pub fn as_slice(&self) -> &[SourceFile<'a>] {
69
4
        self.0.as_slice()
70
4
    }
71

            
72
    pub fn as_args_to(&self, dst: &mut Vec<Argument>) -> Result<()> {
73
        let args = self.0.iter().map(|sf| sf.path()).map(Argument::from);
74

            
75
        dst.extend(args);
76

            
77
        Ok(())
78
    }
79
}