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