Skip to main content

overpass_lib/query/
tag.rs

1use std::{
2    fmt::Write, hash::Hash,
3};
4use crate::{OverpassQL, OverpassQLError, SaniStr};
5#[cfg(doc)]
6use crate::FilterSet;
7
8/// The set of conditions that an element's tags may or may not satisfy. Used to evaluate the contents of [FilterSet]s.
9/// 
10/// [wiki](https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#By_tag_.28has-kv.29)
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
12pub enum TagFilter<'a> {
13    /// Satisfied if a tag with this name/key is present.
14    /// [wiki](https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Exists)
15    Exists(SaniStr<'a>),
16    /// Satisfied if a tag with this name/key is not present.
17    /// [wiki](https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Not_exists)
18    NotExists(SaniStr<'a>),
19    /// Satisfied if a tag with this name/key exists and has the given value.
20    /// [wiki](https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Equals_.28.3D.2C_.21.3D.29)
21    Equals(SaniStr<'a>, SaniStr<'a>),
22    /// Satisfied if a tag with this name/key does not exist, or has a value other than the given one.
23    /// [wiki](https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Equals_.28.3D.2C_.21.3D.29)
24    NotEquals(SaniStr<'a>, SaniStr<'a>),
25    /// Satisfied if a tag with this name/key exists, and has a value that matches the given regular expression.
26    /// [wiki](https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Value_matches_regular_expression_.28.7E.2C_.21.7E.29)
27    Matches(SaniStr<'a>, SaniStr<'a>),
28    /// Satisfied if a tag with this name/key does not exist, or has a value that does not match the given regular expression.
29    /// [wiki](https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Value_matches_regular_expression_.28.7E.2C_.21.7E.29)
30    NotMatches(SaniStr<'a>, SaniStr<'a>),
31    /// Satisfied if a tag whose name/key matches the first regular expression has a value that matches the second regular expression.
32    /// [wiki](https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Key.2Fvalue_matches_regular_expression_.28.7E.22key_regex.22.7E.22value_regex.22.29)
33    NameValueMatches(SaniStr<'a>, SaniStr<'a>),
34}
35
36impl OverpassQL for TagFilter<'_> {
37    fn fmt_oql(&self, f: &mut impl Write) -> Result<(), OverpassQLError> {
38        match self {
39            Self::Exists(n) => write!(f, "[{n}]"),
40            Self::NotExists(n) => write!(f, "[!{n}]"),
41            Self::Equals(n, v) => write!(f, "[{n}={v}]"),
42            Self::NotEquals(n, v) => write!(f, "[{n}!={v}]"),
43            Self::Matches(n, v) => write!(f, "[{n}~{v}]"),
44            Self::NotMatches(n, v) => write!(f, "[{n}!~{v}]"),
45            Self::NameValueMatches(n, v) => write!(f, "[~{n}~{v}]"),
46        }?;
47        Ok(())
48    }
49}
50
51impl<'a> TagFilter<'a> {
52    /// Create a new [Exists](Self::Exists) variant.
53    pub fn exists(name: &'a str) -> Self {
54        Self::Exists(SaniStr(name))
55    }
56    /// Create a new [NotExists](Self::NotExists) variant.
57    pub fn not_exists(name: &'a str) -> Self {
58        Self::NotExists(SaniStr(name))
59    }
60    /// Create a new [Equals](Self::Equals) variant.
61    pub fn equals(name: &'a str, value: &'a str) -> Self {
62        Self::Equals(SaniStr(name), SaniStr(value))
63    }
64    /// Create a new [NotEquals](Self::NotEquals) variant.
65    pub fn not_equals(name: &'a str, value: &'a str) -> Self {
66        Self::NotEquals(SaniStr(name), SaniStr(value))
67    }
68    /// Create a new [Matches](Self::Matches) variant.
69    pub fn matches(name: &'a str, value_pat: &'a str) -> Self {
70        Self::Matches(SaniStr(name), SaniStr(value_pat))
71    }
72    /// Create a new [NotMatches](Self::NotMatches) variant.
73    pub fn not_matches(name: &'a str, value_pat: &'a str) -> Self {
74        Self::NotMatches(SaniStr(name), SaniStr(value_pat))
75    }
76    /// Create a new [NameValueMatches](Self::NameValueMatches) variant.
77    pub fn name_value_matches(name_pat: &'a str, value_pat: &'a str) -> Self {
78        Self::NameValueMatches(SaniStr(name_pat), SaniStr(value_pat))
79    }
80}
81