15#include <userver/formats/common/meta.hpp>
16#include <userver/formats/common/transfer_tag.hpp>
17#include <userver/formats/common/type.hpp>
18#include <userver/utils/assert.hpp>
20USERVER_NAMESPACE_BEGIN
26template <
typename ValueBuilder>
27ValueBuilder GetAtPath(ValueBuilder& parent, std::vector<std::string>&& path, std::size_t path_size) {
28 UINVARIANT(path_size != 0,
"attempt to get a ValueBuilder element on an empty path");
30 return parent[std::move(path[0])];
32 std::optional<ValueBuilder> current_element;
34 current_element.emplace(TransferTag(), parent[std::move(path[0])]);
35 for (std::size_t i = 1; i < path_size - 1; i++) {
36 current_element.emplace(TransferTag(), (*current_element)[std::move(path[i])]);
38 return (*current_element)[std::move(path[path_size - 1])];
47template <
typename Value>
48std::enable_if_t<
common::kIsFormatValue<Value>, Value>
GetAtPath(Value parent,
const std::vector<std::string>& path) {
49 auto current_value = std::move(parent);
50 for (
const auto& current_key : path) {
51 current_value = current_value[current_key];
60template <
typename ValueBuilder>
63 std::vector<std::string>&& path
65 return impl::GetAtPath(parent, std::move(path), path.size());
72template <
typename Value>
73void SetAtPath(
typename Value::Builder& parent, std::vector<std::string>&& path, Value new_value) {
75 parent = std::move(new_value);
77 GetAtPath(parent, std::move(path)) = std::move(new_value);
86template <
typename ValueBuilder>
87void RemoveAtPath(ValueBuilder& parent, std::vector<std::string>&& path) {
89 parent = ValueBuilder();
90 }
else if (path.size() == 1) {
91 parent.Remove(path[0]);
93 auto& key = path[path.size() - 1];
94 impl::GetAtPath(parent, std::move(path), path.size() - 1).Remove(key);