mwapi 0.6.0

A MediaWiki API client library
Documentation
/*
Copyright (C) 2021 Kunal Mehta <legoktm@debian.org>
Copyright (C) 2021 Erutuon

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
use std::collections::{BTreeMap, HashMap};
use std::fmt::Display;

/// How to specify API parameters
///
/// API parameters can be specified in a number of different ways.
/// All the functions are typed to accept `Into<Params>`, so as long
/// as it can be converted into `Params`.
///
/// ```
/// # use std::collections::{BTreeMap, HashMap};
/// # use mwapi::Params;
///
/// let _: Params = HashMap::from([("action", "query"), ("titles", "Main Page")]).into();
/// let _: Params = (&HashMap::from([("action", "query"), ("titles", "Main Page")])).into();
/// let _: Params = BTreeMap::from([("action", "query"), ("titles", "Main Page")]).into();
/// let _: Params = [("action", "query"), ("titles", "Main Page")].into();
/// let _: Params = vec![("action", "query"), ("titles", "Main Page")].into();
/// ```
///
/// See the various `From` implementations below for a complete list.
#[derive(Debug, Clone, Default)]
pub struct Params {
    pub(crate) map: HashMap<String, String>,
}

impl Params {
    pub(crate) fn insert<K: Display, V: Display>(&mut self, key: K, value: V) {
        self.map.insert(key.to_string(), value.to_string());
    }

    pub(crate) fn get(&self, name: &str) -> Option<&String> {
        self.map.get(name)
    }

    /// Get the parameters as a HashMap
    pub fn as_map(&self) -> &HashMap<String, String> {
        &self.map
    }
}

pub(crate) enum RequestParams {
    Get(Params),
    Post(Params),
    #[cfg(feature = "upload")]
    Multipart(crate::upload::params::MultipartParams),
}

impl<P: Display, Q: Display> FromIterator<(P, Q)> for Params {
    fn from_iter<T: IntoIterator<Item = (P, Q)>>(iter: T) -> Self {
        Self {
            map: iter
                .into_iter()
                .map(|(k, v)| (k.to_string(), v.to_string()))
                .collect(),
        }
    }
}

impl<'a, P: Display, Q: Display> FromIterator<&'a (P, Q)> for Params {
    fn from_iter<T: IntoIterator<Item = &'a (P, Q)>>(iter: T) -> Self {
        Self {
            map: iter
                .into_iter()
                .map(|(k, v)| (k.to_string(), v.to_string()))
                .collect(),
        }
    }
}

impl<P: Display, Q: Display> From<Vec<(P, Q)>> for Params {
    fn from(params: Vec<(P, Q)>) -> Self {
        Self::from_iter(params)
    }
}

impl<P: Display, Q: Display> From<&Vec<(P, Q)>> for Params {
    fn from(params: &Vec<(P, Q)>) -> Self {
        Self::from_iter(params)
    }
}

impl<P: Display, Q: Display> From<&[(P, Q)]> for Params {
    fn from(params: &[(P, Q)]) -> Self {
        Self::from_iter(params)
    }
}

impl<P: Display, Q: Display, const LENGTH: usize> From<[(P, Q); LENGTH]>
    for Params
{
    fn from(params: [(P, Q); LENGTH]) -> Self {
        Self::from_iter(params)
    }
}

impl<P: Display, Q: Display, const LENGTH: usize> From<&[(P, Q); LENGTH]>
    for Params
{
    fn from(params: &[(P, Q); LENGTH]) -> Self {
        Self::from_iter(params)
    }
}

impl<P: Display, Q: Display> From<HashMap<P, Q>> for Params {
    fn from(params: HashMap<P, Q>) -> Self {
        Self::from_iter(params)
    }
}

impl<P: Display, Q: Display> From<&HashMap<P, Q>> for Params {
    fn from(params: &HashMap<P, Q>) -> Self {
        Self::from_iter(params)
    }
}

impl<P: Display, Q: Display> From<BTreeMap<P, Q>> for Params {
    fn from(params: BTreeMap<P, Q>) -> Self {
        Self::from_iter(params)
    }
}

impl<P: Display, Q: Display> From<&BTreeMap<P, Q>> for Params {
    fn from(params: &BTreeMap<P, Q>) -> Self {
        Self::from_iter(params)
    }
}

#[test]
fn can_be_created_from_common_types() {
    type HashMap<K, V> = std::collections::HashMap<
        K,
        V,
        std::collections::hash_map::RandomState,
    >;
    macro_rules! convert_to_params {
        (
            $($source: expr,)*
        ) => {
            $(
                let _ = Params::from($source);
                let _ = Params::from_iter($source);
            )*
        };
    }
    convert_to_params!(
        [("a", "b")],
        &[("a", "b")],
        &[("a", "b")][..],
        vec![("a", "b")],
        &vec![("a", "b")],
        HashMap::from_iter([("a", "b")]),
        &HashMap::from_iter([("a", "b")]),
    );
}