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
8USERVER_NAMESPACE_BEGIN
9
10namespace proto_structs::io {
11
12std::string Context::GetCurrentPath(int current_field_number) const {
13 const ::google::protobuf::Descriptor* last_message_desc = nullptr;
14 auto result = GetCurrentPathImpl(last_message_desc);
15
16 if (last_message_desc) {
17 auto field_desc = last_message_desc->FindFieldByNumber(current_field_number);
18
19 if (field_desc) {
20 result.append(fmt::format(".{}", field_desc->name()));
21 } else {
22 result.append(fmt::format(".<unknown_{}>", current_field_number));
23 }
24 }
25
26 return result;
27}
28
29std::string Context::GetCurrentPath(const ::google::protobuf::FieldDescriptor& current_field_desc) const {
30 const ::google::protobuf::Descriptor* last_message_desc = nullptr;
31 auto result = GetCurrentPathImpl(last_message_desc);
32
33 if (last_message_desc) {
34 if (current_field_desc.containing_type() == last_message_desc) {
35 result.append(fmt::format(".{}", current_field_desc.name()));
36 } else {
37 result.append(fmt::format(".<unknown_{}>", current_field_desc.number()));
38 }
39 }
40
41 return result;
42}
43
44std::string Context::GetCurrentPath() const {
45 const ::google::protobuf::Descriptor* last_message_desc = nullptr;
46 return GetCurrentPathImpl(last_message_desc);
47}
48
49std::string Context::GetCurrentPathImpl(const ::google::protobuf::Descriptor*& last_message_desc) const {
50 auto current_ptr = &top_message_desc_;
51
52 std::string result;
53 result.reserve(128);
54 result = current_ptr->full_name();
55
56 for (const auto& field_number : path_) {
57 auto field_desc = current_ptr->FindFieldByNumber(field_number);
58
59 if (field_desc && field_desc->type() == ::google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
60 result.append(fmt::format(".{}", field_desc->name()));
61 current_ptr = field_desc->message_type();
62 } else {
63 result.append(fmt::format(".<unknown_{}>", field_number));
64 current_ptr = nullptr;
65 break;
66 }
67 }
68
69 last_message_desc = current_ptr;
70 return result;
72
73template <typename TError>
74const std::vector<TError>& ContextWithErrors<TError>::GetErrors(utils::impl::InternalTag) const& noexcept {
75 return errors_;
76}
77
78template <typename TError>
79std::vector<TError>&& ContextWithErrors<TError>::GetErrors(utils::impl::InternalTag) && noexcept {
80 return std::move(errors_);
81}
82
83template <typename TError>
84void ContextWithErrors<TError>::AddError(int field_number, std::string_view reason) {
85 AddError(GetCurrentPath(field_number), reason);
86}
87
88template <typename TError>
89void ContextWithErrors<
90 TError>::AddError(const ::google::protobuf::FieldDescriptor& field_desc, std::string_view reason) {
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
109
110USERVER_NAMESPACE_END