Skip to main content

overpass_lib/query/
recurse.rs

1use std::{
2    borrow::Cow,
3    fmt::Write,
4};
5
6use crate::{OverpassQLNamed, OverpassQLError, Namer, Set, SaniStr};
7#[cfg(doc)]
8use crate::{Node, Way, Relation};
9
10/// A filter set criterion based on the element's relationship to other elements.
11/// 
12/// [wiki](https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Recurse_.28n.2C_w.2C_r.2C_bn.2C_bw.2C_br.29)
13#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14pub enum RecurseFilter<'a> {
15    /// Select [Node]s that appear within a [Way] in the provided input [Set].
16    WithinWays { input: Cow<'a, Set<'a>> },
17    /// Select [Node]s/[Way]s that are members of a [Relation] in the provided input [Set]. If a role is specified,
18    /// the element must also have that role in said relations.
19    WithinRelations { input: Cow<'a, Set<'a>>, role: Option<SaniStr<'a>> },
20    /// Select [Way]s/[Relation]s that have a member [Node] in the provided input [Set]. If a role is specified,
21    /// the node must also have that role in said relations.
22    ContainingNodes { input: Cow<'a, Set<'a>>, role: Option<SaniStr<'a>> },
23    /// Select [Relation]s that have a member [Way] in the provided input [Set]. If a role is specified,
24    /// the way must also have that role in said relations.
25    ContainingWays { input: Cow<'a, Set<'a>>, role: Option<SaniStr<'a>> },
26    /// Select [Relation]s that have a member [Relation] in the provided input [Set]. If a role is specified,
27    /// the relation must also have that role in said relations.
28    ContainingRelations { input: Cow<'a, Set<'a>>, role: Option<SaniStr<'a>> },
29}
30
31impl<'a> RecurseFilter<'a> {
32    pub fn input(&self) -> &Set<'a> {
33        match self {
34            Self::WithinWays { input } => input,
35            Self::WithinRelations { input, .. } => input,
36            Self::ContainingNodes { input, .. } => input,
37            Self::ContainingWays { input, .. } => input,
38            Self::ContainingRelations { input, .. } => input,
39        }
40    }
41}
42
43impl<'a> OverpassQLNamed<'a> for RecurseFilter<'a> {
44    fn fmt_oql_named<'b, 'c>(&'b self, f: &mut impl Write, namer: &mut Namer<'a, 'c>)
45    -> Result<(), OverpassQLError>
46    where 'b: 'c {
47        let (code, input, role) = match self {
48            Self::WithinWays { input } => ("w", input, &None),
49            Self::WithinRelations { input, role } => ("r", input, role),
50            Self::ContainingNodes { input, role } => ("bn", input, role),
51            Self::ContainingWays { input, role } => ("bw", input, role),
52            Self::ContainingRelations { input, role } => ("br", input, role),
53        };
54        match (namer.get_or_assign(input), role) {
55            (Some(n), Some(r)) => write!(f, "({code}.{n}:{r}")?,
56            (Some(n), None) => write!(f, "({code}.{n})")?,
57            (None, Some(r)) => write!(f, "({code}:{r}")?,
58            (None, None) => write!(f, "({code})")?,
59        };
60        Ok(())
61    }
62}