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 <grpc/support/port_platform.h>
16
17 #include "src/core/lib/gprpp/validation_errors.h"
18
19 #include <algorithm>
20 #include <utility>
21
22 #include "absl/status/status.h"
23 #include "absl/strings/str_cat.h"
24 #include "absl/strings/str_join.h"
25 #include "absl/strings/strip.h"
26
27 namespace grpc_core {
28
PushField(absl::string_view ext)29 void ValidationErrors::PushField(absl::string_view ext) {
30 // Skip leading '.' for top-level field names.
31 if (fields_.empty()) absl::ConsumePrefix(&ext, ".");
32 fields_.emplace_back(std::string(ext));
33 }
34
PopField()35 void ValidationErrors::PopField() { fields_.pop_back(); }
36
AddError(absl::string_view error)37 void ValidationErrors::AddError(absl::string_view error) {
38 field_errors_[absl::StrJoin(fields_, "")].emplace_back(error);
39 }
40
FieldHasErrors() const41 bool ValidationErrors::FieldHasErrors() const {
42 return field_errors_.find(absl::StrJoin(fields_, "")) != field_errors_.end();
43 }
44
status(absl::StatusCode code,absl::string_view prefix) const45 absl::Status ValidationErrors::status(absl::StatusCode code,
46 absl::string_view prefix) const {
47 if (field_errors_.empty()) return absl::OkStatus();
48 return absl::Status(code, message(prefix));
49 }
50
message(absl::string_view prefix) const51 std::string ValidationErrors::message(absl::string_view prefix) const {
52 if (field_errors_.empty()) return "";
53 std::vector<std::string> errors;
54 for (const auto& p : field_errors_) {
55 if (p.second.size() > 1) {
56 errors.emplace_back(absl::StrCat("field:", p.first, " errors:[",
57 absl::StrJoin(p.second, "; "), "]"));
58 } else {
59 errors.emplace_back(
60 absl::StrCat("field:", p.first, " error:", p.second[0]));
61 }
62 }
63 return absl::StrCat(prefix, ": [", absl::StrJoin(errors, "; "), "]");
64 }
65
66 } // namespace grpc_core
67