1use crate::error::Span;
2
3#[derive(Debug, Clone, PartialEq)]
4pub struct Query {
5 pub expression: Expression,
6 pub span: Span,
7}
8
9#[derive(Debug, Clone, PartialEq)]
10pub enum Expression {
11 BooleanOp {
12 operator: BooleanOperator,
13 left: Box<Expression>,
14 right: Option<Box<Expression>>,
15 span: Span,
16 },
17
18 Group {
19 expression: Box<Expression>,
20 span: Span,
21 },
22
23 Proximity {
24 operator: ProximityOperator,
25 terms: Vec<Expression>,
26 span: Span,
27 },
28
29 Field {
30 field: FieldType,
31 value: Box<Expression>,
32 span: Span,
33 },
34
35 Range {
36 field: Option<FieldType>,
37 start: String,
38 end: String,
39 span: Span,
40 },
41
42 Term {
43 term: Term,
44 span: Span,
45 },
46
47 Comment {
48 text: String,
49 span: Span,
50 },
51}
52
53#[derive(Debug, Clone, PartialEq)]
54pub enum BooleanOperator {
55 And,
56 Or,
57 Not,
58}
59
60impl BooleanOperator {
61 pub fn parse(s: &str) -> Option<Self> {
62 match s {
63 "AND" => Some(Self::And),
64 "OR" => Some(Self::Or),
65 "NOT" => Some(Self::Not),
66 _ => None,
67 }
68 }
69
70 pub fn as_str(&self) -> &'static str {
71 match self {
72 Self::And => "AND",
73 Self::Or => "OR",
74 Self::Not => "NOT",
75 }
76 }
77}
78
79#[derive(Debug, Clone, PartialEq)]
80pub enum ProximityOperator {
81 Proximity { distance: Option<u32> },
82 Near { distance: u32 },
83 NearForward { distance: u32 },
84}
85
86#[derive(Debug, Clone, PartialEq)]
87pub enum FieldType {
88 Title,
89 Site,
90 Url,
91 Author,
92 Links,
93
94 Continent,
95 Country,
96 Region,
97 City,
98 Latitude,
99 Longitude,
100
101 Language,
102 ChannelId,
103
104 AuthorGender,
105 AuthorVerified,
106 AuthorVerifiedType,
107 AuthorFollowers,
108 BlogName,
109 ParentBlogName,
110 RootBlogName,
111 ParentPostId,
112 RootPostId,
113 Tags,
114 BrandIds,
115 Objects,
116 EngagementType,
117 EngagingWith,
118 EngagingWithGuid,
119 Guid,
120 ImageType,
121 ItemReview,
122 Rating,
123 MinuteOfDay,
124 PubType,
125 PublisherSubType,
126 Publication,
127 RedditAuthorFlair,
128 RedditPostFlair,
129 RedditSpoiler,
130 SensitiveContent,
131 Subreddit,
132 SubredditNSFW,
133 SubredditTopics,
134 TopLevelDomain,
135 WeblogTitle,
136 Sentiment,
137}
138
139impl FieldType {
140 pub fn parse(s: &str) -> Option<Self> {
141 match s.to_lowercase().as_str() {
142 "title" => Some(Self::Title),
143 "site" => Some(Self::Site),
144 "url" => Some(Self::Url),
145 "author" => Some(Self::Author),
146 "links" => Some(Self::Links),
147 "continent" => Some(Self::Continent),
148 "country" => Some(Self::Country),
149 "region" => Some(Self::Region),
150 "city" => Some(Self::City),
151 "latitude" => Some(Self::Latitude),
152 "longitude" => Some(Self::Longitude),
153 "language" => Some(Self::Language),
154 "channelid" => Some(Self::ChannelId),
155 "authorgender" => Some(Self::AuthorGender),
156 "authorverified" => Some(Self::AuthorVerified),
157 "authorverifiedtype" => Some(Self::AuthorVerifiedType),
158 "authorfollowers" => Some(Self::AuthorFollowers),
159 "blogname" => Some(Self::BlogName),
160 "parentblogname" => Some(Self::ParentBlogName),
161 "rootblogname" => Some(Self::RootBlogName),
162 "parentpostid" => Some(Self::ParentPostId),
163 "rootpostid" => Some(Self::RootPostId),
164 "tags" => Some(Self::Tags),
165 "brandids" => Some(Self::BrandIds),
166 "objects" => Some(Self::Objects),
167 "engagementtype" => Some(Self::EngagementType),
168 "engagingwith" => Some(Self::EngagingWith),
169 "engagingwithguid" => Some(Self::EngagingWithGuid),
170 "guid" => Some(Self::Guid),
171 "imagetype" => Some(Self::ImageType),
172 "itemreview" => Some(Self::ItemReview),
173 "rating" => Some(Self::Rating),
174 "minuteofday" => Some(Self::MinuteOfDay),
175 "pubtype" => Some(Self::PubType),
176 "publishersubtype" => Some(Self::PublisherSubType),
177 "publication" => Some(Self::Publication),
178 "redditauthorflair" => Some(Self::RedditAuthorFlair),
179 "redditpostflair" => Some(Self::RedditPostFlair),
180 "redditspoiler" => Some(Self::RedditSpoiler),
181 "sensitivecontent" => Some(Self::SensitiveContent),
182 "subreddit" => Some(Self::Subreddit),
183 "subredditnsfw" => Some(Self::SubredditNSFW),
184 "subreddittopics" => Some(Self::SubredditTopics),
185 "topleveldomain" => Some(Self::TopLevelDomain),
186 "weblogtitle" => Some(Self::WeblogTitle),
187 "sentiment" => Some(Self::Sentiment),
188 _ => None,
189 }
190 }
191
192 pub fn as_str(&self) -> &'static str {
193 match self {
194 Self::Title => "title",
195 Self::Site => "site",
196 Self::Url => "url",
197 Self::Author => "author",
198 Self::Links => "links",
199 Self::Continent => "continent",
200 Self::Country => "country",
201 Self::Region => "region",
202 Self::City => "city",
203 Self::Latitude => "latitude",
204 Self::Longitude => "longitude",
205 Self::Language => "language",
206 Self::ChannelId => "channelId",
207 Self::AuthorGender => "authorGender",
208 Self::AuthorVerified => "authorVerified",
209 Self::AuthorVerifiedType => "authorVerifiedType",
210 Self::AuthorFollowers => "authorFollowers",
211 Self::BlogName => "blogName",
212 Self::ParentBlogName => "parentBlogName",
213 Self::RootBlogName => "rootBlogName",
214 Self::ParentPostId => "parentPostId",
215 Self::RootPostId => "rootPostId",
216 Self::Tags => "tags",
217 Self::BrandIds => "brandIds",
218 Self::Objects => "objects",
219 Self::EngagementType => "engagementType",
220 Self::EngagingWith => "engagingWith",
221 Self::EngagingWithGuid => "engagingWithGuid",
222 Self::Guid => "guid",
223 Self::ImageType => "imageType",
224 Self::ItemReview => "itemReview",
225 Self::Rating => "rating",
226 Self::MinuteOfDay => "minuteOfDay",
227 Self::PubType => "pubType",
228 Self::PublisherSubType => "publisherSubType",
229 Self::Publication => "publication",
230 Self::RedditAuthorFlair => "redditAuthorFlair",
231 Self::RedditPostFlair => "redditPostFlair",
232 Self::RedditSpoiler => "redditSpoiler",
233 Self::SensitiveContent => "sensitiveContent",
234 Self::Subreddit => "subreddit",
235 Self::SubredditNSFW => "subredditNSFW",
236 Self::SubredditTopics => "subredditTopics",
237 Self::TopLevelDomain => "topLevelDomain",
238 Self::WeblogTitle => "weblogTitle",
239 Self::Sentiment => "sentiment",
240 }
241 }
242}
243
244#[derive(Debug, Clone, PartialEq)]
245pub enum Term {
246 Word { value: String },
247 Phrase { value: String },
248 Wildcard { value: String },
249 Replacement { value: String },
250 CaseSensitive { value: String },
251 Hashtag { value: String },
252 Mention { value: String },
253 Emoji { value: String },
254}