use crate::commands::{buffer::Buffer, ParticleType};
use crate::errors::Result;
use crate::{CollectionIndexType, Value};
#[derive(Debug, Clone)]
pub struct Filter {
#[doc(hidden)]
pub bin_name: String,
collection_index_type: CollectionIndexType,
value_particle_type: ParticleType,
#[doc(hidden)]
pub begin: Value,
#[doc(hidden)]
pub end: Value,
}
impl Filter {
#[doc(hidden)]
pub fn new(
bin_name: &str,
collection_index_type: CollectionIndexType,
value_particle_type: ParticleType,
begin: Value,
end: Value,
) -> Self {
Filter {
bin_name: bin_name.to_owned(),
collection_index_type,
value_particle_type,
begin,
end,
}
}
#[doc(hidden)]
pub fn collection_index_type(&self) -> CollectionIndexType {
self.collection_index_type.clone()
}
#[doc(hidden)]
pub fn estimate_size(&self) -> Result<usize> {
Ok(self.bin_name.len() + self.begin.estimate_size()? + self.end.estimate_size()? + 10)
}
#[doc(hidden)]
pub fn write(&self, buffer: &mut Buffer) -> Result<()> {
buffer.write_u8(self.bin_name.len() as u8)?;
buffer.write_str(&self.bin_name)?;
buffer.write_u8(self.value_particle_type.clone() as u8)?;
buffer.write_u32(self.begin.estimate_size()? as u32)?;
self.begin.write_to(buffer)?;
buffer.write_u32(self.end.estimate_size()? as u32)?;
self.end.write_to(buffer)?;
Ok(())
}
}
#[macro_export]
macro_rules! as_eq {
($bin_name:expr, $val:expr) => {{
let val = as_val!($val);
$crate::query::Filter::new(
$bin_name,
$crate::CollectionIndexType::Default,
val.particle_type(),
val.clone(),
val.clone(),
)
}};
}
#[macro_export]
macro_rules! as_range {
($bin_name:expr, $begin:expr, $end:expr) => {{
let begin = as_val!($begin);
let end = as_val!($end);
$crate::query::Filter::new(
$bin_name,
$crate::CollectionIndexType::Default,
begin.particle_type(),
begin,
end,
)
}};
}
#[macro_export]
macro_rules! as_contains {
($bin_name:expr, $val:expr, $cit:expr) => {{
let val = as_val!($val);
$crate::query::Filter::new(
$bin_name,
$cit,
val.particle_type(),
val.clone(),
val.clone(),
)
}};
}
#[macro_export]
macro_rules! as_contains_range {
($bin_name:expr, $begin:expr, $end:expr, $cit:expr) => {{
let begin = as_val!($begin);
let end = as_val!($end);
$crate::query::Filter::new($bin_name, $cit, begin.particle_type(), begin, end)
}};
}
#[macro_export]
macro_rules! as_within_region {
($bin_name:expr, $region:expr) => {{
let cit = $crate::CollectionIndexType::Default;
let region = as_geo!(String::from($region));
$crate::query::Filter::new(
$bin_name,
cit,
region.particle_type(),
region.clone(),
region.clone(),
)
}};
($bin_name:expr, $region:expr, $cit:expr) => {{
let region = as_geo!(String::from($region));
$crate::query::Filter::new(
$bin_name,
$cit,
region.particle_type(),
region.clone(),
region.clone(),
)
}};
}
#[macro_export]
macro_rules! as_within_radius {
($bin_name:expr, $lat:expr, $lng:expr, $radius:expr) => {{
let cit = $crate::CollectionIndexType::Default;
let lat = as_val!($lat as f64);
let lng = as_val!($lng as f64);
let radius = as_val!($radius as f64);
let geo_json = format!(
"{{ \"type\": \"Aeroircle\", \"coordinates\": [[{:.8}, {:.8}], {}] }}",
lng, lat, radius
);
let geo_json = as_geo!(geo_json);
$crate::query::Filter::new(
$bin_name,
cit,
geo_json.particle_type(),
geo_json.clone(),
geo_json.clone(),
)
}};
($bin_name:expr, $lat:expr, $lng:expr, $radius:expr, $cit:expr) => {{
let lat = as_val!($lat as f64);
let lng = as_val!($lng as f64);
let radius = as_val!($radius as f64);
let geo_json = format!(
"{{ \"type\": \"Aeroircle\", \"coordinates\": [[{:.8}, {:.8}], {}] }}",
lng, lat, radius
);
let geo_json = as_geo!(geo_json);
$crate::query::Filter::new(
$bin_name,
$cit,
geo_json.particle_type(),
geo_json.clone(),
geo_json.clone(),
)
}};
}
#[macro_export]
macro_rules! as_regions_containing_point {
($bin_name:expr, $point:expr) => {{
let cit = $crate::CollectionIndexType::Default;
let point = as_geo!(String::from($point));
$crate::query::Filter::new(
$bin_name,
cit,
point.particle_type(),
point.clone(),
point.clone(),
)
}};
($bin_name:expr, $point:expr, $cit:expr) => {{
let point = as_geo!(String::from($point));
$crate::query::Filter::new(
$bin_name,
$cit,
point.particle_type(),
point.clone(),
point.clone(),
)
}};
}
#[cfg(test)]
mod tests {
use super::CollectionIndexType;
#[test]
fn geo_filter_macros() {
let geo_filter = as_within_region!("bin1", "{}");
assert_eq!(geo_filter.bin_name, "bin1");
let geo_filter = as_within_region!("bin1", "{}", CollectionIndexType::MapValues);
assert_eq!(geo_filter.bin_name, "bin1");
let geo_filter = as_regions_containing_point!("bin1", "{}");
assert_eq!(geo_filter.bin_name, "bin1");
let geo_filter = as_regions_containing_point!("bin1", "{}", CollectionIndexType::MapValues);
assert_eq!(geo_filter.bin_name, "bin1");
let geo_filter = as_within_radius!("bin1", 1, 3, 7);
assert_eq!(geo_filter.bin_name, "bin1");
let geo_filter = as_within_radius!("bin1", 1, 3, 7, CollectionIndexType::List);
assert_eq!(geo_filter.bin_name, "bin1");
}
}