lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

cli.rs (2930B)


      1 #![cfg(feature = "cli")]
      2 
      3 use clap::Parser;
      4 use config::{Map, Value};
      5 use serde::de::DeserializeOwned;
      6 use std::path::{Path, PathBuf};
      7 
      8 use crate::error::{RuntimeCliError, RuntimeError};
      9 
     10 pub fn parse_and_load_path<Args, C, FP>(path_of: FP) -> Result<(Args, C), RuntimeError>
     11 where
     12     Args: Parser,
     13     C: DeserializeOwned,
     14     FP: Fn(&Args) -> Option<&Path>,
     15 {
     16     let args = Args::try_parse().map_err(RuntimeCliError::from)?;
     17     let path = resolve_path(path_of(&args))?;
     18     let cfg = crate::config::load_required_file::<C>(&path)?;
     19     Ok((args, cfg))
     20 }
     21 
     22 pub fn parse_and_load_path_with_env_overrides<Args, C, FP, FO>(
     23     path_of: FP,
     24     env_prefix: Option<&str>,
     25     overrides_of: FO,
     26 ) -> Result<(Args, C), RuntimeError>
     27 where
     28     Args: Parser,
     29     C: DeserializeOwned,
     30     FP: Fn(&Args) -> Option<&Path>,
     31     FO: Fn(&Args) -> Option<Map<String, Value>>,
     32 {
     33     let args = Args::try_parse().map_err(RuntimeCliError::from)?;
     34     let path = resolve_path(path_of(&args))?;
     35     let cfg = crate::config::load_required_file_with_env_and_overrides::<C>(
     36         &path,
     37         env_prefix,
     38         overrides_of(&args),
     39     )?;
     40     Ok((args, cfg))
     41 }
     42 
     43 pub fn parse_and_load_path_with_init<Args, C, FP, FL>(
     44     path_of: FP,
     45     logs_dir_of: FL,
     46     default_level: Option<&str>,
     47 ) -> Result<(Args, C), RuntimeError>
     48 where
     49     Args: Parser,
     50     C: DeserializeOwned,
     51     FP: Fn(&Args) -> Option<&Path>,
     52     FL: Fn(&C) -> &str,
     53 {
     54     let (args, cfg) = parse_and_load_path::<Args, C, FP>(path_of)?;
     55     crate::tracing::init_with_logs_dir(Path::new(logs_dir_of(&cfg)), default_level)?;
     56     Ok((args, cfg))
     57 }
     58 
     59 pub fn parse_and_load_path_with_env_overrides_and_init<Args, C, FP, FO, FL>(
     60     path_of: FP,
     61     env_prefix: Option<&str>,
     62     overrides_of: FO,
     63     logs_dir_of: FL,
     64     default_level: Option<&str>,
     65 ) -> Result<(Args, C), RuntimeError>
     66 where
     67     Args: Parser,
     68     C: DeserializeOwned,
     69     FP: Fn(&Args) -> Option<&Path>,
     70     FO: Fn(&Args) -> Option<Map<String, Value>>,
     71     FL: Fn(&C) -> &str,
     72 {
     73     let (args, cfg) = parse_and_load_path_with_env_overrides::<Args, C, FP, FO>(
     74         path_of,
     75         env_prefix,
     76         overrides_of,
     77     )?;
     78     crate::tracing::init_with_logs_dir(Path::new(logs_dir_of(&cfg)), default_level)?;
     79     Ok((args, cfg))
     80 }
     81 
     82 #[inline]
     83 fn resolve_path(p: Option<&Path>) -> Result<PathBuf, RuntimeCliError> {
     84     p.map(Path::to_path_buf)
     85         .ok_or(RuntimeCliError::MissingConfigPath)
     86 }
     87 
     88 #[cfg(test)]
     89 mod tests {
     90     use std::path::PathBuf;
     91 
     92     use super::resolve_path;
     93     use crate::RuntimeCliError;
     94 
     95     #[test]
     96     fn resolve_path_requires_explicit_path() {
     97         let err = resolve_path(None).expect_err("missing path should error");
     98         assert!(matches!(err, RuntimeCliError::MissingConfigPath));
     99 
    100         let path = PathBuf::from("/tmp/config.toml");
    101         assert_eq!(
    102             resolve_path(Some(path.as_path())).expect("path should resolve"),
    103             path
    104         );
    105     }
    106 }