#pragma once
#include "clock.hpp"
#include "cow_string.hpp"
#include "exception.hpp"
#include "exclusion/common.hpp"
#include "iterator.hpp"
#include "object.hpp"
#include "transformer/base.hpp"
#include "transformer/manager.hpp"
#include <cstdint>
#include <optional>
#include <span>
#include <string_view>
#include <variant>
#include <vector>
namespace ddwaf {
template <typename IteratorType = kv_iterator> class transforming_iterator {
public:
explicit transforming_iterator(object_view obj, std::span<const transformer_id> transformers,
const object_set_ref &exclude, ddwaf::timer &deadline)
: it_(obj, {}, exclude), transformers_(transformers), deadline_(deadline)
{
advance_to_transformable_object();
}
~transforming_iterator() = default;
transforming_iterator(const transforming_iterator &) = delete;
transforming_iterator(transforming_iterator &&) = delete;
transforming_iterator &operator=(const transforming_iterator &) = delete;
transforming_iterator &operator=(transforming_iterator &&) = delete;
[[nodiscard]] std::string_view current_value() const
{
if (current_param_.has_value()) {
return static_cast<std::string_view>(current_param_.value());
}
return {};
}
[[nodiscard]] object_view operator*()
{
auto value = current_value();
const char *data = value.data() != nullptr ? value.data() : "";
current_object_ = owned_object::make_string_literal(data, value.size());
return current_object_;
}
bool operator++()
{
++it_;
return advance_to_transformable_object();
}
[[nodiscard]] explicit operator bool() const { return static_cast<bool>(it_); }
[[nodiscard]] std::vector<std::variant<std::string_view, int64_t>> get_current_path() const
{
return it_.get_current_path();
}
protected:
bool advance_to_transformable_object()
{
for (; it_; ++it_) {
if (deadline_.expired()) {
throw ddwaf::timeout_exception();
}
const object_view current_obj = *it_;
if (!current_obj.is_string()) {
continue;
}
current_param_ = transformer::manager::transform(current_obj, transformers_);
if (!current_param_.has_value()) {
current_param_ = cow_string{current_obj.template as<std::string_view>()};
}
return true;
}
return false;
}
std::optional<cow_string> current_param_;
owned_object current_object_;
IteratorType it_;
std::span<const transformer_id> transformers_;
ddwaf::timer &deadline_;
};
}