Skip to content

Commit b2b5fdc

Browse files
committed
Add a composible "read" function
1 parent a6908cd commit b2b5fdc

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

mdio/coordinate_selector.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)