@@ -26,6 +26,25 @@ void timer(std::chrono::high_resolution_clock::time_point start) {
2626}
2727#endif
2828
29+ // — helper to tag multi-key sorts ——
30+ template <typename T>
31+ struct SortKey {
32+ std::string key;
33+ using value_type = T;
34+ };
35+
36+ // — trait to detect ValueDescriptor<T> ——
37+ template <typename D> struct is_value_descriptor : std::false_type {};
38+ template <typename T> struct is_value_descriptor <ValueDescriptor<T>> : std::true_type {};
39+ template <typename D>
40+ inline constexpr bool is_value_descriptor_v = is_value_descriptor<std::decay_t <D>>::value;
41+
42+ // — trait to detect SortKey<T> ——
43+ template <typename D> struct is_sort_key : std::false_type {};
44+ template <typename T> struct is_sort_key <SortKey<T>> : std::true_type {};
45+ template <typename D>
46+ inline constexpr bool is_sort_key_v = is_sort_key<std::decay_t <D>>::value;
47+
2948// / \brief Collects valid index selections per dimension for a Dataset without
3049// / performing slicing immediately.
3150// /
@@ -37,7 +56,24 @@ class CoordinateSelector {
3756 explicit CoordinateSelector (const Dataset& dataset)
3857 : dataset_(dataset), base_domain_(dataset.domain) {}
3958
59+ template <typename OutT, typename ... Ops>
60+ Future<std::vector<OutT>> ReadDataVariable (const std::string& data_variable, Ops const &... ops) {
61+ // 1) apply filters & sorts in the exact order given
62+ absl::Status st = absl::OkStatus ();
63+ ((st = st.ok () ? _applyOp (ops).status () : st), ...);
64+ if (!st.ok ()) return st;
4065
66+ // 2) finally read out the requested variable
67+ return readSelection<OutT>(data_variable);
68+ }
69+
70+ /* *
71+ * @brief Filter the Dataset by the given coordinate.
72+ * Limitations:
73+ * - Only a single filter is currently tested.
74+ * - A bug exists if the filter value does not make a perfect hyper-rectangle within its dimensions.
75+ *
76+ */
4177 template <typename T>
4278 mdio::Future<void > filterByCoordinate (const ValueDescriptor<T>& descriptor) {
4379 if (kept_runs_.empty ()) {
@@ -167,6 +203,28 @@ class CoordinateSelector {
167203 tensorstore::IndexDomain<> base_domain_;
168204 std::vector<std::vector<mdio::RangeDescriptor<mdio::Index>>> kept_runs_;
169205
206+ template <typename D>
207+ Future<void > _applyOp (D const & op) {
208+ if constexpr (is_value_descriptor_v<D>) {
209+ auto fut = filterByCoordinate (op);
210+ if (!fut.status ().ok ()) {
211+ return fut.status ();
212+ }
213+ return absl::OkStatus ();
214+ } else if constexpr (is_sort_key_v<D>) {
215+ using SortT = typename std::decay_t <D>::value_type;
216+ auto fut = sortSelectionByKey<SortT>(op.key );
217+ if (!fut.status ().ok ()) {
218+ return fut.status ();
219+ }
220+ return absl::OkStatus ();
221+ } else {
222+ return absl::UnimplementedError (
223+ " query(): RangeDescriptor and ListDescriptor not supported" );
224+ }
225+ }
226+
227+
170228 /*
171229 TODO: The built RangeDescriptors aren't behaving as I hoped.
172230 They are building the longest runs possible properly, however
0 commit comments