use criterium::sql::Field;
use criterium::CriteriumChainBuilder;
use serde::{Serialize,Deserialize};
use url::Url;
use criterium::DirectMatch;
use criterium::NumberCriterium;
use criterium::rusqlite::assembler::*;
use criterium::StringCriterium;
use crate::database::fields::*;
use crate::Origin;
#[derive(Clone,Debug,Serialize,Deserialize)]
#[serde(rename_all="snake_case")]
pub enum OriginCriterium {
Scheme(StringCriterium),
Host(StringCriterium),
Port(NumberCriterium<u16>),
Equals(Origin),
}
impl OriginCriterium {
pub fn parse_host(host: String) -> Self {
let start_dot = host.starts_with(".");
return OriginCriterium::Host(
if host.ends_with(".") {
if start_dot {
StringCriterium::Contains(host)
} else {
StringCriterium::HasPrefix(host)
}
} else if start_dot {
StringCriterium::HasSuffix(host)
} else {
StringCriterium::Equals(host)
}
);
}
}
impl<F: Field + From<OriginField>> AssembleRusqliteQuery<F ,()> for OriginCriterium {
fn assemble_rusqlite_query(
&self,
assembly_context: &AssemblyContext,
_context: &()
) -> InvertableRusqliteQuery<F> {
match self {
Self::Scheme(c) => c.assemble_query(assembly_context, &OriginField::Scheme.into()),
Self::Host(c) => c.assemble_query(assembly_context, &OriginField::Host.into()),
Self::Port(c) => c.assemble_query(assembly_context, &OriginField::Port.into()),
Self::Equals(origin) => {
let mut builder = CriteriumChainBuilder::and(false) ;
builder.add_criterium(Self::Scheme(origin.scheme.clone().into()));
builder.add_criterium(Self::Host(origin.host.clone().into()));
builder.add_criterium(Self::Port(origin.port.into()));
builder.to_chain().assemble_rusqlite_query(assembly_context, &())
}
}
}
}
impl DirectMatch<Origin> for OriginCriterium {
type Output = bool;
fn criterium_match(&self, data: &Origin) -> bool {
match self {
Self::Scheme(c) => c.criterium_match(&data.scheme),
Self::Host(c) => c.criterium_match(&data.host.as_ref()),
Self::Port(c) => c.criterium_match(&data.port),
Self::Equals(origin) => origin == data,
}
}
}
impl DirectMatch<Url> for OriginCriterium {
type Output = bool;
fn criterium_match(&self, data: &Url) -> bool {
match self {
Self::Scheme(c) => c.criterium_match(data.scheme()),
Self::Host(c) => c.criterium_match(&data.host_str()),
Self::Port(c) => c.criterium_match(&data.port_or_known_default()),
Self::Equals(origin) =>
origin.host.as_deref() == data.host_str() &&
origin.port == data.port() &&
origin.scheme == data.scheme(),
}
}
}