1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include <cstdlib>
9 #include <string>
10
11 #include "absl/strings/cord.h"
12 #include "absl/strings/match.h"
13 #include "absl/strings/str_cat.h"
14 #include "absl/strings/string_view.h"
15 #include "google/protobuf/any.h"
16 #include "google/protobuf/generated_message_util.h"
17 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
18 #include "google/protobuf/message_lite.h"
19
20 namespace google {
21 namespace protobuf {
22 namespace internal {
23
24 using UrlType = std::string;
25 using ValueType = std::string;
26
27 const char kAnyFullTypeName[] = "google.protobuf.Any";
28 const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
29 const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/";
30
GetTypeUrl(absl::string_view message_name,absl::string_view type_url_prefix)31 std::string GetTypeUrl(absl::string_view message_name,
32 absl::string_view type_url_prefix) {
33 if (!type_url_prefix.empty() &&
34 type_url_prefix[type_url_prefix.size() - 1] == '/') {
35 return absl::StrCat(type_url_prefix, message_name);
36 } else {
37 return absl::StrCat(type_url_prefix, "/", message_name);
38 }
39 }
40
EndsWithTypeName(absl::string_view type_url,absl::string_view type_name)41 bool EndsWithTypeName(absl::string_view type_url, absl::string_view type_name) {
42 return type_url.size() > type_name.size() &&
43 type_url[type_url.size() - type_name.size() - 1] == '/' &&
44 absl::EndsWith(type_url, type_name);
45 }
46
InternalPackFromLite(const MessageLite & message,absl::string_view type_url_prefix,absl::string_view type_name,UrlType * dst_url,ValueType * dst_value)47 bool InternalPackFromLite(const MessageLite& message,
48 absl::string_view type_url_prefix,
49 absl::string_view type_name, UrlType* dst_url,
50 ValueType* dst_value) {
51 *dst_url = GetTypeUrl(type_name, type_url_prefix);
52 return message.SerializeToString(dst_value);
53 }
54
InternalUnpackToLite(absl::string_view type_name,absl::string_view type_url,const ValueType & value,MessageLite * dst_message)55 bool InternalUnpackToLite(absl::string_view type_name,
56 absl::string_view type_url, const ValueType& value,
57 MessageLite* dst_message) {
58 if (!InternalIsLite(type_name, type_url)) {
59 return false;
60 }
61 return dst_message->ParseFromString(value);
62 }
63
InternalIsLite(absl::string_view type_name,absl::string_view type_url)64 bool InternalIsLite(absl::string_view type_name, absl::string_view type_url) {
65 return EndsWithTypeName(type_url, type_name);
66 }
67
ParseAnyTypeUrl(absl::string_view type_url,std::string * url_prefix,std::string * full_type_name)68 bool ParseAnyTypeUrl(absl::string_view type_url, std::string* url_prefix,
69 std::string* full_type_name) {
70 size_t pos = type_url.find_last_of('/');
71 if (pos == std::string::npos || pos + 1 == type_url.size()) {
72 return false;
73 }
74 if (url_prefix) {
75 *url_prefix = std::string(type_url.substr(0, pos + 1));
76 }
77 *full_type_name = std::string(type_url.substr(pos + 1));
78 return true;
79 }
80
ParseAnyTypeUrl(absl::string_view type_url,std::string * full_type_name)81 bool ParseAnyTypeUrl(absl::string_view type_url, std::string* full_type_name) {
82 return ParseAnyTypeUrl(type_url, nullptr, full_type_name);
83 }
84
85 } // namespace internal
86 } // namespace protobuf
87 } // namespace google
88