chaser-oxide 0.2.2

Undetectable browser automation library
Documentation
use std::collections::HashMap;
use std::fmt;

pub struct ArgsBuilder(HashMap<String, Vec<String>>);

impl ArgsBuilder {
    pub fn new() -> Self {
        Self(HashMap::new())
    }

    pub fn has(&self, key: &str) -> bool {
        self.0.contains_key(key)
    }

    pub fn arg<T: Into<Arg>>(&mut self, arg: T) -> &mut Self {
        let arg = arg.into();
        if let Some(values) = self.0.get_mut(&arg.key) {
            values.extend(arg.values);
        } else {
            self.0.insert(arg.key, arg.values);
        }
        self
    }

    pub fn args<T: Into<Arg>>(&mut self, args: impl IntoIterator<Item = T>) -> &mut Self {
        for arg in args {
            self.arg(arg);
        }
        self
    }

    pub fn into_iter(self) -> impl Iterator<Item = String> {
        self.0.into_iter().map(|(key, values)| {
            if values.is_empty() {
                format!("--{}", key)
            } else {
                format!("--{}={}", key, values.join(","))
            }
        })
    }
}

#[derive(Debug, Clone)]
pub struct Arg {
    key: String,
    values: Vec<String>,
}

impl Arg {
    pub fn key(key: impl AsRef<str>) -> Self {
        Self {
            key: key.as_ref().to_string(),
            values: Vec::new(),
        }
    }

    pub fn value(key: impl AsRef<str>, value: impl fmt::Display) -> Self {
        Self {
            key: key.as_ref().to_string(),
            values: vec![value.to_string()],
        }
    }

    pub fn values(
        key: impl AsRef<str>,
        values: impl IntoIterator<Item = impl fmt::Display>,
    ) -> Self {
        Self {
            key: key.as_ref().to_string(),
            values: values.into_iter().map(|v| v.to_string()).collect(),
        }
    }
}

impl From<(&str, &str)> for Arg {
    fn from((key, value): (&str, &str)) -> Self {
        Self {
            key: key.to_string(),
            values: vec![value.to_string()],
        }
    }
}

impl From<(&str, &[&str])> for Arg {
    fn from((key, values): (&str, &[&str])) -> Self {
        Self {
            key: key.to_string(),
            values: values.iter().map(|v| v.to_string()).collect(),
        }
    }
}

impl From<&str> for Arg {
    fn from(value: &str) -> Self {
        Self {
            key: value.to_string(),
            values: Vec::new(),
        }
    }
}

impl From<String> for Arg {
    fn from(value: String) -> Self {
        Self {
            key: value,
            values: Vec::new(),
        }
    }
}

impl From<ArgConst> for Arg {
    fn from(arg: ArgConst) -> Self {
        Self {
            key: arg.key.to_string(),
            values: arg.values.iter().map(|v| v.to_string()).collect(),
        }
    }
}

#[derive(Debug, Clone)]
pub struct ArgConst {
    key: &'static str,
    values: &'static [&'static str],
}

impl ArgConst {
    pub const fn key(key: &'static str) -> Self {
        Self { key, values: &[] }
    }

    pub const fn values(key: &'static str, values: &'static [&'static str]) -> Self {
        Self { key, values }
    }
}