use std::collections::HashMap;
use std::fs::File;
use std::io;
use std::path::Path;
use serde_derive::Deserialize;
#[derive(Debug, Deserialize)]
pub struct Account {
#[serde(deserialize_with = "deserialize_jid")]
pub jid: xmpp_parsers::Jid,
pub password: String,
#[serde(default, deserialize_with = "deserialize_jid_map")]
pub chatrooms: HashMap<String, xmpp_parsers::Jid>,
pub ping: Option<u64>,
}
#[derive(Debug, Deserialize)]
pub struct Config {
pub account: Account,
pub http: std::net::SocketAddr,
}
impl Config {
pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Self> {
use std::io::Read;
let mut f = File::open(path)?;
let mut buffer = String::new();
f.read_to_string(&mut buffer)?;
Ok(toml::from_str(&buffer).unwrap())
}
}
fn deserialize_jid<'de, D>(deserializer: D) -> Result<xmpp_parsers::Jid, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::Deserialize;
let s = String::deserialize(deserializer)?;
std::str::FromStr::from_str(&s).map_err(serde::de::Error::custom)
}
fn deserialize_jid_map<'de, D>(
deserializer: D,
) -> Result<HashMap<String, xmpp_parsers::Jid>, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::Deserialize;
let s = HashMap::<String, String>::deserialize(deserializer)?;
let size = s.len();
s.into_iter()
.map(|(k, v)| (k, std::str::FromStr::from_str(&v)))
.take_while(|(_k, r)| r.is_ok())
.fold(Ok(HashMap::with_capacity(size)), |res, (k, r)| match res {
Ok(mut res) => match r {
Ok(v) => {
res.insert(k, v);
Ok(res)
}
Err(e) => Err(e),
},
Err(e) => Err(e),
})
.map_err(serde::de::Error::custom)
}