RUFF/src/config.rs
2021-07-26 23:58:04 +02:00

158 lines
5.1 KiB
Rust

use crate::meme::{Matcher, Meme, MemeIdent};
use serde::{
de::{self, Deserializer, MapAccess, Visitor},
Deserialize,
};
use std::path::PathBuf;
use url::Url;
#[derive(Debug, Deserialize)]
pub struct Config {
pub homeserver_url: Url,
pub user_id: String,
pub password: String,
pub device_name: Option<String>,
pub sendmeme_command: Option<String>,
pub memes: Vec<Meme>,
pub store_path: PathBuf,
#[serde(default = "default_clear_threshold")]
pub clear_cache_threshold: u32,
}
fn default_clear_threshold() -> u32 {
10
}
impl<'de> Deserialize<'de> for Meme {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
const FIELDS: &[&str] = &["keyword", "id", "randomcat"];
enum Field {
Keyword,
Ident(IdentField),
Matcher,
MatchCase,
}
enum IdentField {
RandomCat,
Id,
}
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct Vis;
impl<'de> Visitor<'de> for Vis {
type Value = Field;
fn expecting(
&self,
fmt: &mut std::fmt::Formatter<'_>,
) -> Result<(), std::fmt::Error> {
fmt.write_str("a field for a meme")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(match v {
"keyword" => Field::Keyword,
"randomcat" => Field::Ident(IdentField::RandomCat),
"id" => Field::Ident(IdentField::Id),
"match" => Field::Matcher,
"match_case" => Field::MatchCase,
_ => return Err(de::Error::unknown_field(v, FIELDS)),
})
}
}
deserializer.deserialize_identifier(Vis)
}
}
struct Vis;
impl<'de> Visitor<'de> for Vis {
type Value = Meme;
fn expecting(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
fmt.write_str("a meme")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut keyword = None;
let mut ident = None;
let mut matcher = None;
let mut match_case = None;
while let Some(key) = map.next_key()? {
match key {
Field::Keyword => {
if keyword.is_some() {
return Err(de::Error::duplicate_field("keyword"));
}
keyword = Some(map.next_value()?);
},
Field::Ident(i) => {
if ident.is_some() {
return Err(de::Error::duplicate_field(
"ident, can only have one.",
));
}
match i {
IdentField::Id => {
ident = Some(MemeIdent::Id(map.next_value()?));
},
IdentField::RandomCat => {
ident = Some(MemeIdent::RandomCat(map.next_value()?));
},
}
},
Field::Matcher => {
if matcher.is_some() {
return Err(de::Error::duplicate_field("match"));
}
matcher = Some(map.next_value()?);
},
Field::MatchCase => {
if match_case.is_some() {
return Err(de::Error::duplicate_field("match"));
}
match_case = Some(map.next_value()?);
},
}
}
let keyword = keyword.ok_or_else(|| de::Error::missing_field("keyword"))?;
let ident = ident.ok_or_else(|| de::Error::missing_field("ident"))?;
let matcher = matcher.unwrap_or(Matcher::Begins);
let match_case = match_case.unwrap_or(false);
Ok(Meme {
keyword,
ident,
matcher,
match_case,
})
}
}
deserializer.deserialize_struct("Meme", FIELDS, Vis)
}
}