parsingrustclap

Rust parsing variable


Hi guys I'm trying to parse a some values here:

#[clap(
       long,
       env = "TODAY_COSTUMERS",
       value_delimiter = ',',
   )]
   pub(crate) costumers: Vec<String>,

When I do

export TODAY_COSTUMERS=""

Instead of this vec![] I'm getting this vec![""], which causes an error.

I've tried this:

    #[clap(
        long,
        env = "TODAY_COSTUMERS",
        value_delimiter = ',',
        value_parser = parse_comma_separated
    )]
    pub(crate) costumers: Vec<String>,

// using this function:
pub fn parse_comma_separated(s: &str) -> Result<Vec<String>, String> {
    if s.is_empty() {
        Ok(vec![])
    } else {
        let values: Vec<String> = s
            .split(',')
            .map(|s| s.trim().to_string())
            .filter(|s| !s.is_empty())
            .collect();
        Ok(values)
    }
}

But at the end get this error from clap:

Mismatch between definition and access of today_costumers. Could not downcast to alloc::string::String, need to downcast to alloc::vec::Vecalloc::string::String

Any idea how to solve this?


Solution

  • At the end I solved it using this approach not happy but at least works fine. I was looking for a something easier:
    `

    
    #[clap(
     long,
     env = "TODAY_COSTUMERS",
     value_delimiter = ',',
    )]
    pub(crate) costumers: Costumers,
    
    #[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
    pub struct Costumers(Vec<String>);
    
    impl FromStr for Costumers {
        type Err = String;
    
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            if s.is_empty() {
                Ok(Costumers(vec![]))
            } else {
                let values: Vec<String> = s
                    .split(',')
                    .map(|v| v.trim().to_string())
                    .filter(|v| !v.is_empty())
                    .collect();
                Ok(Costumers(values))
            }
        }
    }
    
    impl<'a> IntoIterator for &'a GRPCFallbacks {
        type Item = &'a String;
        type IntoIter = std::slice::Iter<'a, String>;
    
        fn into_iter(self) -> Self::IntoIter {
            self.0.iter()
        }
    }
    
    impl Deref for Costumers {
        type Target = Vec<String>;
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }