mas_i18n/sprintf/
argument.rsuse std::collections::HashMap;
use serde_json::Value;
#[derive(Debug, Clone, Default)]
pub struct List {
    arguments: Vec<Value>,
    name_index: HashMap<String, usize>,
}
impl List {
    #[must_use]
    pub fn get_by_index(&self, index: usize) -> Option<&Value> {
        self.arguments.get(index)
    }
    #[must_use]
    pub fn get_by_name(&self, name: &str) -> Option<&Value> {
        self.name_index
            .get(name)
            .and_then(|index| self.get_by_index(*index))
    }
}
impl<A: Into<Argument>> FromIterator<A> for List {
    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
        let mut arguments = Vec::new();
        let mut name_index = HashMap::new();
        for (index, argument) in iter.into_iter().enumerate() {
            let argument = argument.into();
            if let Some(name) = argument.name {
                name_index.insert(name.clone(), index);
            }
            arguments.push(argument.value);
        }
        Self {
            arguments,
            name_index,
        }
    }
}
pub struct Argument {
    name: Option<String>,
    value: Value,
}
impl From<Value> for Argument {
    fn from(value: Value) -> Self {
        Self { name: None, value }
    }
}
impl From<(&str, Value)> for Argument {
    fn from((name, value): (&str, Value)) -> Self {
        Self {
            name: Some(name.to_owned()),
            value,
        }
    }
}
impl From<(String, Value)> for Argument {
    fn from((name, value): (String, Value)) -> Self {
        Self {
            name: Some(name),
            value,
        }
    }
}
impl Argument {
    #[must_use]
    pub fn named(name: String, value: Value) -> Self {
        Self {
            name: Some(name),
            value,
        }
    }
    #[must_use]
    pub fn with_name(mut self, name: String) -> Self {
        self.name = Some(name);
        self
    }
}
#[cfg(test)]
mod tests {
    use serde_json::json;
    use super::*;
    #[test]
    fn test_argument_list() {
        let list = List::from_iter([
            ("hello", json!("world")),
            ("alice", json!(null)),
            ("bob", json!(42)),
        ]);
        assert_eq!(list.get_by_index(0), Some(&json!("world")));
        assert_eq!(list.get_by_index(1), Some(&json!(null)));
        assert_eq!(list.get_by_index(2), Some(&json!(42)));
        assert_eq!(list.get_by_index(3), None);
        assert_eq!(list.get_by_name("hello"), Some(&json!("world")));
        assert_eq!(list.get_by_name("alice"), Some(&json!(null)));
        assert_eq!(list.get_by_name("bob"), Some(&json!(42)));
        assert_eq!(list.get_by_name("charlie"), None);
        let list = List::from_iter([
            Argument::from(json!("hello")),
            Argument::named("alice".to_owned(), json!(null)),
            Argument::named("bob".to_owned(), json!(42)),
        ]);
        assert_eq!(list.get_by_index(0), Some(&json!("hello")));
        assert_eq!(list.get_by_index(1), Some(&json!(null)));
        assert_eq!(list.get_by_index(2), Some(&json!(42)));
        assert_eq!(list.get_by_index(3), None);
        assert_eq!(list.get_by_name("hello"), None);
        assert_eq!(list.get_by_name("alice"), Some(&json!(null)));
        assert_eq!(list.get_by_name("bob"), Some(&json!(42)));
        assert_eq!(list.get_by_name("charlie"), None);
    }
}