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