1#include <userver/proto-structs/io/context.hpp>
4#include <google/protobuf/descriptor.h>
6#include <userver/utils/impl/internal_tag.hpp>
8namespace proto_structs::io {
10std::string Context::GetCurrentPath(
int current_field_number)
const {
11 const ::google::protobuf::Descriptor* last_message_desc =
nullptr;
12 auto result = GetCurrentPathImpl(last_message_desc);
14 if (last_message_desc) {
15 auto field_desc = last_message_desc->FindFieldByNumber(current_field_number);
18 result.append(fmt::format(
".{}", field_desc->name()));
20 result.append(fmt::format(
".<unknown_{}>", current_field_number));
27std::string Context::GetCurrentPath(
const ::google::protobuf::FieldDescriptor& current_field_desc)
const {
28 const ::google::protobuf::Descriptor* last_message_desc =
nullptr;
29 auto result = GetCurrentPathImpl(last_message_desc);
31 if (last_message_desc) {
32 if (current_field_desc.containing_type() == last_message_desc) {
33 result.append(fmt::format(
".{}", current_field_desc.name()));
35 result.append(fmt::format(
".<unknown_{}>", current_field_desc.number()));
42std::string Context::GetCurrentPath()
const {
43 const ::google::protobuf::Descriptor* last_message_desc =
nullptr;
44 return GetCurrentPathImpl(last_message_desc);
47std::string Context::GetCurrentPathImpl(
const ::google::protobuf::Descriptor*& last_message_desc)
const {
48 auto current_ptr = &top_message_desc_;
52 result = current_ptr->full_name();
54 for (
const auto& field_number : path_) {
55 auto field_desc = current_ptr->FindFieldByNumber(field_number);
57 if (field_desc && field_desc->type() == ::google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
58 result.append(fmt::format(
".{}", field_desc->name()));
59 current_ptr = field_desc->message_type();
61 result.append(fmt::format(
".<unknown_{}>", field_number));
62 current_ptr =
nullptr;
67 last_message_desc = current_ptr;
71template <
typename TError>
72const std::vector<TError>& ContextWithErrors<TError>::GetErrors(utils::impl::InternalTag)
const&
noexcept {
76template <
typename TError>
77std::vector<TError>&& ContextWithErrors<TError>::GetErrors(utils::impl::InternalTag) &&
noexcept {
78 return std::move(errors_);
81template <
typename TError>
82void ContextWithErrors<TError>::AddError(
int field_number, std::string_view reason) {
83 AddError(GetCurrentPath(field_number), reason);
86template <
typename TError>
87void ContextWithErrors<TError>::AddError(
88 const ::google::protobuf::FieldDescriptor& field_desc,
89 std::string_view reason
91 AddError(GetCurrentPath(field_desc), reason);
94template <
typename TError>
95void ContextWithErrors<TError>::AddError(std::string_view reason) {
96 AddError(GetCurrentPath(), reason);
99template <
typename TError>
100void ContextWithErrors<TError>::AddError(std::string_view path, std::string_view reason) {
101 errors_.emplace_back(path, reason);
102 throw Error{errors_.back()};
105template class ContextWithErrors<ReadError>;
106template class ContextWithErrors<WriteError>;