Skip to main content

az_rs/
api.rs

1use crate::arg::CliInput;
2use anyhow::{anyhow, Result};
3use clap::ArgMatches;
4use invoke::CommandInvocation;
5use std::path::PathBuf;
6
7pub mod invoke;
8pub mod metadata;
9
10#[derive(Debug, Clone)]
11pub struct ApiManager {
12    #[allow(dead_code)]
13    path: PathBuf,
14    rps: Vec<String>,
15}
16
17impl ApiManager {
18    pub fn build_invocation(
19        &self,
20        raw_input: &CliInput,
21        matches: &ArgMatches,
22    ) -> Result<CommandInvocation> {
23        let pos_args = raw_input.pos_args();
24        pos_args
25            .first()
26            .ok_or(anyhow!("the rp is not specified"))
27            .and_then(|rp| {
28                let c = self.read_metadata(rp)?.resolve_command(&raw_input)?;
29                Ok(CommandInvocation::new(&c, matches))
30            })
31    }
32}
33
34#[cfg(any(feature = "embed-api", target_arch = "wasm32"))]
35mod embedded {
36    use crate::api::metadata::Metadata;
37    use anyhow::{anyhow, Result};
38    use std::path::PathBuf;
39
40    use rust_embed::RustEmbed;
41
42    #[derive(RustEmbed)]
43    #[folder = "metadata/"]
44    struct Asset;
45
46    impl super::ApiManager {
47        pub fn new(_: PathBuf) -> Result<Self> {
48            let rps: Vec<String> = Asset::names()
49                .map(|name| name.trim_end_matches(".json").to_string())
50                .collect();
51            Ok(Self {
52                path: PathBuf::new(),
53                rps,
54            })
55        }
56
57        pub fn list_rps(&self) -> &Vec<String> {
58            &self.rps
59        }
60
61        pub fn read_metadata(&self, rp: &str) -> Result<Metadata> {
62            let bytes: Vec<u8> = Asset::get(format!("{rp}.json").as_str())
63                .map(|d| d.data.to_vec())
64                .ok_or(anyhow!("{rp}.json doesn't exist"))?;
65            Ok(serde_json::from_slice(&bytes)?)
66        }
67    }
68}
69
70#[cfg(not(any(feature = "embed-api", target_arch = "wasm32")))]
71mod fs {
72    use crate::api::metadata::Metadata;
73    use anyhow::{Context, Result};
74    use std::path::PathBuf;
75
76    use std::fs::read;
77
78    impl super::ApiManager {
79        pub fn new(path: PathBuf) -> Result<Self> {
80            // TODO: Validate the path
81            let mut rps = vec![];
82            for entry in path
83                .read_dir()
84                .context(format!("reading dir {}", path.display()))?
85            {
86                let path = entry?.path();
87                if let Some(ext) = path.extension() {
88                    if ext == "json" {
89                        if let Some(stem) = path.file_stem().and_then(|s| s.to_str()) {
90                            rps.push(stem.to_owned());
91                        }
92                    }
93                }
94            }
95            Ok(Self { path, rps })
96        }
97
98        pub fn list_rps(&self) -> &Vec<String> {
99            &self.rps
100        }
101
102        pub fn read_metadata(&self, rp: &str) -> Result<Metadata> {
103            let bytes =
104                read(self.path.join(format!("{rp}.json"))).context(format!("reading {rp}.json"))?;
105            Ok(serde_json::from_slice(&bytes)?)
106        }
107    }
108}