1 // Copyright 2020 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/core/util/validation_errors.h"
16
17 #include <grpc/support/port_platform.h>
18 #include <inttypes.h>
19
20 #include <utility>
21
22 #include "absl/log/log.h"
23 #include "absl/status/status.h"
24 #include "absl/strings/str_cat.h"
25 #include "absl/strings/str_join.h"
26 #include "absl/strings/strip.h"
27
28 namespace grpc_core {
29
PushField(absl::string_view ext)30 void ValidationErrors::PushField(absl::string_view ext) {
31 // Skip leading '.' for top-level field names.
32 if (fields_.empty()) absl::ConsumePrefix(&ext, ".");
33 fields_.emplace_back(std::string(ext));
34 }
35
PopField()36 void ValidationErrors::PopField() { fields_.pop_back(); }
37
AddError(absl::string_view error)38 void ValidationErrors::AddError(absl::string_view error) {
39 auto key = absl::StrJoin(fields_, "");
40 if (field_errors_[key].size() >= max_error_count_) {
41 VLOG(2) << "Ignoring validation error: too many errors found ("
42 << max_error_count_ << ")";
43 return;
44 }
45 field_errors_[key].emplace_back(error);
46 }
47
FieldHasErrors() const48 bool ValidationErrors::FieldHasErrors() const {
49 return field_errors_.find(absl::StrJoin(fields_, "")) != field_errors_.end();
50 }
51
status(absl::StatusCode code,absl::string_view prefix) const52 absl::Status ValidationErrors::status(absl::StatusCode code,
53 absl::string_view prefix) const {
54 if (field_errors_.empty()) return absl::OkStatus();
55 return absl::Status(code, message(prefix));
56 }
57
message(absl::string_view prefix) const58 std::string ValidationErrors::message(absl::string_view prefix) const {
59 if (field_errors_.empty()) return "";
60 std::vector<std::string> errors;
61 for (const auto& p : field_errors_) {
62 if (p.second.size() > 1) {
63 errors.emplace_back(absl::StrCat("field:", p.first, " errors:[",
64 absl::StrJoin(p.second, "; "), "]"));
65 } else {
66 errors.emplace_back(
67 absl::StrCat("field:", p.first, " error:", p.second[0]));
68 }
69 }
70 return absl::StrCat(prefix, ": [", absl::StrJoin(errors, "; "), "]");
71 }
72
73 } // namespace grpc_core
74