overpass_lib/query/
filter.rs1use std::{
2 borrow::Cow,
3 collections::{hash_set::IntoIter, HashSet},
4 fmt::Write,
5};
6use crate::{
7 Bbox, Namer, OverpassQLError, OverpassQLNamed, OverpassQL, RecurseFilter, Set, TagFilter
8};
9#[cfg(doc)]
10use crate::{Node, Way, Relation};
11
12#[derive(Debug, Clone, Copy, Default)]
14pub enum FilterType {
15 Node,
17 Way,
19 Relation,
21 #[default]
23 Any,
24 NodeOrWay,
25 NodeOrRelation,
26 WayOrRelation,
27 Area,
31}
32
33impl OverpassQL for FilterType {
34 fn fmt_oql(&self, f: &mut impl Write) -> Result<(), OverpassQLError> {
35 match self {
36 Self::Node => write!(f, "node")?,
37 Self::Way => write!(f, "way")?,
38 Self::Relation => write!(f, "relation")?,
39 Self::Any => write!(f, "nwr")?,
40 Self::NodeOrWay => write!(f, "nw")?,
41 Self::NodeOrRelation => write!(f, "nr")?,
42 Self::WayOrRelation => write!(f, "wr")?,
43 Self::Area => write!(f, "area")?,
45 }
46 Ok(())
47 }
48}
49
50impl<'a> Into<Set<'a>> for FilterType {
51 fn into(self) -> Set<'a> {
52 Set::Filter(FilterSet { filter_type: self, ..Default::default() })
53 }
54}
55
56#[derive(Debug, Clone, Default)]
58pub struct FilterSet<'a> {
59 pub filter_type: FilterType,
62
63 pub inputs: HashSet<Cow<'a, Set<'a>>>,
67
68 pub id_filters: HashSet<i64>,
72
73 pub tag_filters: HashSet<TagFilter<'a>>,
76
77 pub bbox_filter: Option<Bbox>,
80
81 pub recurse_filters: HashSet<RecurseFilter<'a>>,
84}
85
86impl<'a> OverpassQLNamed<'a> for FilterSet<'a> {
87 fn fmt_oql_named<'b, 'c>(&'b self, f: &mut impl Write, namer: &mut Namer<'a, 'c>)
88 -> Result<(), OverpassQLError>
89 where 'b: 'c {
90 self.filter_type.fmt_oql(f)?;
91
92 for input in &self.inputs {
93 if let Some(name) = namer.get_or_assign(input) {
94 write!(f, ".{name}")?;
95 }
96 }
97
98 if self.id_filters.len() > 0 {
99 let mut iter = self.id_filters.iter();
100 write!(f, "(id:{}", iter.next().unwrap())?;
101 for i in iter {
102 write!(f, ",{i}")?;
103 }
104 write!(f, ")")?;
105 }
106
107 if let Some(bbox) = &self.bbox_filter {
108 write!(f, "(")?;
109 bbox.fmt_oql(f)?;
110 write!(f, ")")?;
111 }
112
113 for filter in &self.tag_filters {
114 filter.fmt_oql(f)?;
115 }
116
117 for filter in &self.recurse_filters {
118 filter.fmt_oql_named(f, namer)?;
119 }
120
121 Ok(())
122 }
123}
124
125impl<'a> FilterSet<'a> {
126 pub fn dependencies(&self) -> IntoIter<&Set<'a>> {
128 self.inputs.iter().map(|i| i.as_ref())
129 .chain(self.recurse_filters.iter().map(|r| r.input()))
130 .collect::<HashSet<_>>().into_iter()
131 }
132}