use criterium::BooleanJoiner;
use criterium::DirectMatch;
use criterium::rusqlite::assembler::*;
use criterium::StringCriterium;
use criterium::sql::Field;
use mediatype::MediaTypeBuf;
use mediatype::Name;
use mediatype::ReadParams;
use serde::{Serialize,Deserialize};
use crate::database::fields::*;
#[derive(Clone,Debug,Serialize,Deserialize)]
#[serde(rename_all="snake_case")]
pub enum MimeCriterium {
MimeType(StringCriterium),
MimeSubtype(StringCriterium),
MimeSuffix(StringCriterium),
MimeHasParameter(String, StringCriterium),
IsNone,
}
impl MimeCriterium {
pub fn assemble_rusqlite_query<F: Field + From<MimetypeField> + From<MimeParameterField>> (
&self,
assembly_context: &AssemblyContext,
dock_prefix: &Prefix,
mimetype_id_field: &F,
) -> InvertableRusqliteQuery<F> {
match self {
Self::MimeType(c) =>
c.assemble_query(
assembly_context,
&MimetypeField::MimeType.into()
),
Self::MimeSubtype(c) =>
c.assemble_query(
assembly_context,
&MimetypeField::MimeSubtype.into()
),
Self::MimeSuffix(c) =>
c.assemble_query(
assembly_context,
&MimetypeField::MimeSuffix.into()
),
Self::MimeHasParameter(p,c) => {
let p = p.to_ascii_lowercase();
if p == "charset" {
c.assemble_query(
assembly_context,
&MimetypeField::Charset.into()
)
} else {
let param_assembly_context = assembly_context.prefix_with_unique_reason(
"mimetype_param_",
Some(BooleanJoiner::Or)
);
let value_query = c.assemble_query(
¶m_assembly_context.in_and_block(),
&MimeParameterField::Value.into(),
).get_corrected_query();
let kc = StringCriterium::Equals(p.clone());
let key_query = kc.assemble_query(
¶m_assembly_context.in_and_block(),
&MimeParameterField::Key.into(),
).get_corrected_query();
value_query
.and(key_query)
.parenthesise_where_clause()
.left_join( None,
MimeParameterField::MimetypeId.into(),
Some(assembly_context.prefix()),
MimetypeField::MimetypeId.into()
).as_invertable()
}
},
Self::IsNone => {
return RusqliteQuery::test_if_null(
dock_prefix,
mimetype_id_field,
false
).as_invertable();
}
}.inner_join(
None,
MimetypeField::MimetypeId.into(),
Some(dock_prefix),
mimetype_id_field.clone()
)
}
}
impl DirectMatch<MediaTypeBuf> for MimeCriterium {
type Output = bool;
fn criterium_match(&self, data: &MediaTypeBuf) -> bool {
match self {
Self::MimeType(c) => c.criterium_match(data.ty().as_str()),
Self::MimeSubtype(c) => c.criterium_match(data.subty().as_str()),
Self::MimeSuffix(c) => c.criterium_match(&data.suffix().map(|s| s.as_str())),
Self::MimeHasParameter(key, c) => {
if let Some(key) = Name::new(key) {
return c.criterium_match(&data.get_param(key).map(|v| v.as_str()));
}
return false;
},
Self::IsNone => false,
}
}
}
impl DirectMatch<Option<MediaTypeBuf>> for MimeCriterium {
type Output = bool;
fn criterium_match(&self, data: &Option<MediaTypeBuf>) -> bool {
match (self,data) {
(Self::IsNone,data) => data.is_none(),
(c, Some(d)) => c.criterium_match(d),
(_, None) => false,
}
}
}