userver: /data/code/userver/libraries/proto-structs/src/proto-structs/io/context_base.cpp Source File
Loading...
Searching...
No Matches
context_base.cpp
1#include <userver/proto-structs/io/context.hpp>
2
3#include <fmt/format.h>
4#include <google/protobuf/descriptor.h>
5
6#include <userver/utils/impl/internal_tag.hpp>
7
8namespace proto_structs::io {
9
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);
13
14 if (last_message_desc) {
15 auto field_desc = last_message_desc->FindFieldByNumber(current_field_number);
16
17 if (field_desc) {
18 result.append(fmt::format(".{}", field_desc->name()));
19 } else {
20 result.append(fmt::format(".<unknown_{}>", current_field_number));
21 }
22 }
23
24 return result;
25}
26
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);
30
31 if (last_message_desc) {
32 if (current_field_desc.containing_type() == last_message_desc) {
33 result.append(fmt::format(".{}", current_field_desc.name()));
34 } else {
35 result.append(fmt::format(".<unknown_{}>", current_field_desc.number()));
36 }
37 }
38
39 return result;
40}
41
42std::string Context::GetCurrentPath() const {
43 const ::google::protobuf::Descriptor* last_message_desc = nullptr;
44 return GetCurrentPathImpl(last_message_desc);
45}
46
47std::string Context::GetCurrentPathImpl(const ::google::protobuf::Descriptor*& last_message_desc) const {
48 auto current_ptr = &top_message_desc_;
49
50 std::string result;
51 result.reserve(128);
52 result = current_ptr->full_name();
53
54 for (const auto& field_number : path_) {
55 auto field_desc = current_ptr->FindFieldByNumber(field_number);
56
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();
60 } else {
61 result.append(fmt::format(".<unknown_{}>", field_number));
62 current_ptr = nullptr;
63 break;
64 }
65 }
66
67 last_message_desc = current_ptr;
68 return result;
69}
70
71template <typename TError>
72const std::vector<TError>& ContextWithErrors<TError>::GetErrors(utils::impl::InternalTag) const& noexcept {
73 return errors_;
74}
75
76template <typename TError>
77std::vector<TError>&& ContextWithErrors<TError>::GetErrors(utils::impl::InternalTag) && noexcept {
78 return std::move(errors_);
79}
80
81template <typename TError>
82void ContextWithErrors<TError>::AddError(int field_number, std::string_view reason) {
83 AddError(GetCurrentPath(field_number), reason);
84}
85
86template <typename TError>
87void ContextWithErrors<TError>::AddError(
88 const ::google::protobuf::FieldDescriptor& field_desc,
89 std::string_view reason
90) {
91 AddError(GetCurrentPath(field_desc), reason);
92}
93
94template <typename TError>
95void ContextWithErrors<TError>::AddError(std::string_view reason) {
96 AddError(GetCurrentPath(), reason);
97}
98
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()};
103}
104
105template class ContextWithErrors<ReadError>;
106template class ContextWithErrors<WriteError>;
107
108} // namespace proto_structs::io