cmsis_cffi/
config.rs

1use std::fs::{create_dir_all, OpenOptions};
2use std::io::{BufRead, BufReader, Write};
3use std::path::{Path, PathBuf};
4
5use cmsis_pack::update::DownloadConfig;
6
7use anyhow::{anyhow, Error};
8
9pub const DEFAULT_VIDX_LIST: [&str; 1] = ["http://www.keil.com/pack/index.pidx"];
10
11pub struct Config {
12    pack_store: PathBuf,
13}
14
15#[derive(Default)]
16pub struct ConfigBuilder {
17    pack_store: Option<PathBuf>,
18}
19
20impl DownloadConfig for Config {
21    fn pack_store(&self) -> PathBuf {
22        self.pack_store.clone()
23    }
24}
25
26impl ConfigBuilder {
27    pub fn with_pack_store<T: Into<PathBuf>>(self, ps: T) -> Self {
28        Self {
29            pack_store: Some(ps.into()),
30        }
31    }
32
33    pub fn build(self) -> Result<Config, Error> {
34        let pack_store = match self.pack_store {
35            Some(ps) => ps,
36            None => {
37                return Err(anyhow!("Pack Store missing"));
38            }
39        };
40        Ok(Config { pack_store })
41    }
42}
43
44impl Config {
45    pub fn new() -> Result<Config, Error> {
46        ConfigBuilder::default().build()
47    }
48}
49
50pub fn read_vidx_list(vidx_list: &Path) -> Vec<String> {
51    let fd = OpenOptions::new().read(true).open(vidx_list);
52    match fd.map_err(Error::from) {
53        Ok(r) => BufReader::new(r)
54            .lines()
55            .enumerate()
56            .flat_map(|(linenum, line)| {
57                line.map_err(|e| log::error!("Could not parse line #{}: {}", linenum, e))
58                    .into_iter()
59            })
60            .collect(),
61        Err(_) => {
62            log::warn!("Failed to open vendor index list read only. Recreating.");
63            let new_content: Vec<String> =
64                DEFAULT_VIDX_LIST.iter().map(|s| String::from(*s)).collect();
65            match vidx_list.parent() {
66                Some(par) => {
67                    create_dir_all(par).unwrap_or_else(|e| {
68                        log::error!(
69                            "Could not create parent directory for vendor index list.\
70                             Error: {}",
71                            e
72                        );
73                    });
74                }
75                None => {
76                    log::error!("Could not get parent directory for vendors.list");
77                }
78            }
79            match OpenOptions::new().create(true).write(true).open(vidx_list) {
80                Ok(mut fd) => {
81                    let lines = new_content.join("\n");
82                    fd.write_all(lines.as_bytes()).unwrap_or_else(|e| {
83                        log::error!("Could not create vendor list file: {}", e);
84                    });
85                }
86                Err(e) => log::error!("Could not open vendors index list file for writing {}", e),
87            }
88            new_content
89        }
90    }
91}