Skip to main content

blue_build_recipe/
module_ext.rs

1use std::{
2    collections::HashSet,
3    fs,
4    path::{Path, PathBuf},
5};
6
7use bon::Builder;
8use log::trace;
9use miette::{Context, IntoDiagnostic, Report, Result};
10use serde::{Deserialize, Serialize};
11
12use crate::{AkmodsInfo, FromFileList, Module, base_recipe_path};
13
14#[derive(Default, Serialize, Clone, Deserialize, Debug, Builder)]
15pub struct ModuleExt {
16    #[builder(default)]
17    pub modules: Vec<Module>,
18}
19
20impl FromFileList for ModuleExt {
21    const LIST_KEY: &'static str = "modules";
22
23    fn get_from_file_paths(&self) -> Vec<PathBuf> {
24        self.modules
25            .iter()
26            .filter_map(Module::get_from_file_path)
27            .collect()
28    }
29}
30
31impl TryFrom<&PathBuf> for ModuleExt {
32    type Error = Report;
33
34    fn try_from(value: &PathBuf) -> std::result::Result<Self, Self::Error> {
35        Self::try_from(value.as_path())
36    }
37}
38
39impl TryFrom<&Path> for ModuleExt {
40    type Error = Report;
41
42    fn try_from(file_name: &Path) -> Result<Self> {
43        let file_path = base_recipe_path().join(file_name);
44
45        let file = fs::read_to_string(&file_path)
46            .into_diagnostic()
47            .with_context(|| format!("Failed to open {}", file_path.display()))?;
48
49        serde_yaml::from_str::<Self>(&file).map_or_else(
50            |_| -> Result<Self> {
51                let module = serde_yaml::from_str::<Module>(&file)
52                    .into_diagnostic()
53                    .wrap_err_with(|| {
54                        format!("Failed to parse module file {}", file_path.display())
55                    })?;
56                Ok(Self::builder().modules(vec![module]).build())
57            },
58            Ok,
59        )
60    }
61}
62
63impl ModuleExt {
64    #[must_use]
65    pub fn get_akmods_info_list(&self, os_version: &u64) -> Vec<AkmodsInfo> {
66        trace!("get_akmods_image_list({self:#?}, {os_version})");
67
68        let mut seen = HashSet::new();
69
70        self.modules
71            .iter()
72            .filter(|module| {
73                module
74                    .required_fields
75                    .as_ref()
76                    .is_some_and(|rf| rf.module_type.typ() == "akmods")
77            })
78            .filter_map(|module| {
79                Some(
80                    module
81                        .required_fields
82                        .as_ref()?
83                        .generate_akmods_info(os_version),
84                )
85            })
86            .filter(|image| seen.insert(image.clone()))
87            .collect()
88    }
89}