xref: /aosp_15_r20/external/icing/icing/query/advanced_query_parser/pending-value.h (revision 8b6cd535a057e39b3b86660c4aa06c99747c2136)
1 // Copyright (C) 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #ifndef ICING_QUERY_ADVANCED_QUERY_PARSER_PENDING_VALUE_H_
15 #define ICING_QUERY_ADVANCED_QUERY_PARSER_PENDING_VALUE_H_
16 
17 #include <cstdint>
18 #include <memory>
19 #include <string>
20 #include <string_view>
21 #include <utility>
22 #include <vector>
23 
24 #include "icing/text_classifier/lib3/utils/base/status.h"
25 #include "icing/text_classifier/lib3/utils/base/statusor.h"
26 #include "icing/absl_ports/canonical_errors.h"
27 #include "icing/absl_ports/str_cat.h"
28 #include "icing/index/iterator/doc-hit-info-iterator.h"
29 #include "icing/util/status-macros.h"
30 
31 namespace icing {
32 namespace lib {
33 
34 enum class DataType {
35   kNone,
36   kLong,
37   kDouble,
38   kText,
39   kString,
40   kStringList,
41   kDocumentIterator,
42   // TODO(b/326656531): Instead of creating a vector index type, consider
43   // changing it to vector type so that the data is the vector directly.
44   kVectorIndex,
45 };
46 
47 struct QueryTerm {
48   std::string term;
49   std::string_view raw_term;
50   bool is_prefix_val;
51 };
52 
53 // A holder for intermediate results when processing child nodes.
54 struct PendingValue {
CreateStringPendingValuePendingValue55   static PendingValue CreateStringPendingValue(QueryTerm str) {
56     return PendingValue(std::move(str), DataType::kString);
57   }
58 
CreateTextPendingValuePendingValue59   static PendingValue CreateTextPendingValue(QueryTerm text) {
60     return PendingValue(std::move(text), DataType::kText);
61   }
62 
CreateVectorIndexPendingValuePendingValue63   static PendingValue CreateVectorIndexPendingValue(int64_t vector_index) {
64     return PendingValue(vector_index, DataType::kVectorIndex);
65   }
66 
PendingValuePendingValue67   PendingValue() : data_type_(DataType::kNone) {}
68 
PendingValuePendingValue69   explicit PendingValue(std::unique_ptr<DocHitInfoIterator> iterator)
70       : iterator_(std::move(iterator)),
71         data_type_(DataType::kDocumentIterator) {}
72 
PendingValuePendingValue73   explicit PendingValue(std::vector<std::string> string_lists)
74       : string_vals_(std::move(string_lists)),
75         data_type_(DataType::kStringList) {}
76 
77   PendingValue(const PendingValue&) = delete;
78   PendingValue(PendingValue&&) = default;
79 
80   PendingValue& operator=(const PendingValue&) = delete;
81   PendingValue& operator=(PendingValue&&) = default;
82 
83   // Placeholder is used to indicate where the children of a particular node
84   // begin.
is_placeholderPendingValue85   bool is_placeholder() const { return data_type_ == DataType::kNone; }
86 
87   libtextclassifier3::StatusOr<std::unique_ptr<DocHitInfoIterator>>
iteratorPendingValue88   iterator() && {
89     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kDocumentIterator));
90     return std::move(iterator_);
91   }
92 
string_valsPendingValue93   libtextclassifier3::StatusOr<const std::vector<std::string>*> string_vals()
94       const& {
95     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kStringList));
96     return &string_vals_;
97   }
string_valsPendingValue98   libtextclassifier3::StatusOr<std::vector<std::string>> string_vals() && {
99     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kStringList));
100     return std::move(string_vals_);
101   }
102 
string_valPendingValue103   libtextclassifier3::StatusOr<const QueryTerm*> string_val() const& {
104     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kString));
105     return &query_term_;
106   }
string_valPendingValue107   libtextclassifier3::StatusOr<QueryTerm> string_val() && {
108     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kString));
109     return std::move(query_term_);
110   }
111 
text_valPendingValue112   libtextclassifier3::StatusOr<const QueryTerm*> text_val() const& {
113     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kText));
114     return &query_term_;
115   }
text_valPendingValue116   libtextclassifier3::StatusOr<QueryTerm> text_val() && {
117     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kText));
118     return std::move(query_term_);
119   }
120 
long_valPendingValue121   libtextclassifier3::StatusOr<int64_t> long_val() {
122     ICING_RETURN_IF_ERROR(ParseInt());
123     return long_val_;
124   }
125 
double_valPendingValue126   libtextclassifier3::StatusOr<double> double_val() {
127     ICING_RETURN_IF_ERROR(ParseDouble());
128     return double_val_;
129   }
130 
vector_index_valPendingValue131   libtextclassifier3::StatusOr<int64_t> vector_index_val() const {
132     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kVectorIndex));
133     return long_val_;
134   }
135 
136   // Attempts to interpret the value as an int. A pending value can be parsed as
137   // an int under two circumstances:
138   //   1. It holds a kText value which can be parsed to an int
139   //   2. It holds a kLong value
140   // If #1 is true, then the parsed value will be stored in long_value and
141   // data_type will be updated to kLong.
142   // RETURNS:
143   //   - OK, if able to successfully parse the value into a long
144   //   - INVALID_ARGUMENT if the value could not be parsed as a long
145   libtextclassifier3::Status ParseInt();
146 
147   // Attempts to interpret the value as a double. A pending value can be parsed
148   // as a double under two circumstances:
149   //   1. It holds a kText value which can be parsed to a double
150   //   2. It holds a kDouble value
151   // If #1 is true, then the parsed value will be stored in double_val_ and
152   // data_type will be updated to kDouble.
153   // RETURNS:
154   //   - OK, if able to successfully parse the value into a double
155   //   - INVALID_ARGUMENT if the value could not be parsed as a double
156   libtextclassifier3::Status ParseDouble();
157 
data_typePendingValue158   DataType data_type() const { return data_type_; }
159 
160  private:
PendingValuePendingValue161   explicit PendingValue(QueryTerm query_term, DataType data_type)
162       : query_term_(std::move(query_term)), data_type_(data_type) {}
163 
PendingValuePendingValue164   explicit PendingValue(int64_t long_val, DataType data_type)
165       : long_val_(long_val), data_type_(data_type) {}
166 
CheckDataTypePendingValue167   libtextclassifier3::Status CheckDataType(DataType required_data_type) const {
168     if (data_type_ == required_data_type) {
169       return libtextclassifier3::Status::OK;
170     }
171     return absl_ports::InvalidArgumentError(
172         absl_ports::StrCat("Unable to retrieve value of type '",
173                            std::to_string(static_cast<int>(required_data_type)),
174                            "' from pending value of type '",
175                            std::to_string(static_cast<int>(data_type_)), "'"));
176   }
177 
178   // iterator_ will be populated when data_type_ is kDocumentIterator.
179   std::unique_ptr<DocHitInfoIterator> iterator_;
180 
181   // string_vals_ will be populated when data_type_ kStringList.
182   std::vector<std::string> string_vals_;
183 
184   // query_term_ will be populated when data_type_ is kString or kText
185   QueryTerm query_term_;
186 
187   // long_val_ will be populated when data_type_ is kLong - after a successful
188   // call to ParseInt.
189   int64_t long_val_;
190   // double_val_ will be populated when data_type_ is kDouble - after a
191   // successful call to ParseDouble.
192   double double_val_;
193   DataType data_type_;
194 };
195 
196 }  // namespace lib
197 }  // namespace icing
198 
199 #endif  // ICING_QUERY_ADVANCED_QUERY_PARSER_PENDING_VALUE_H_
200