You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by mp...@apache.org on 2015/09/15 10:24:46 UTC

[4/4] mesos git commit: Introduced conversion from JSON arrays to repeated protobuf messages.

Introduced conversion from JSON arrays to repeated protobuf messages.

Review: https://reviews.apache.org/r/37826


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/475d7e55
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/475d7e55
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/475d7e55

Branch: refs/heads/master
Commit: 475d7e55bd80d7619ff25737c62b116db0aeb5e1
Parents: bf72ab6
Author: Alexander Rukletsov <ru...@gmail.com>
Authored: Tue Sep 15 03:01:44 2015 -0500
Committer: Michael Park <mp...@apache.org>
Committed: Tue Sep 15 03:24:28 2015 -0500

----------------------------------------------------------------------
 .../3rdparty/stout/include/stout/protobuf.hpp   | 86 ++++++++++++++++----
 1 file changed, 70 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/475d7e55/3rdparty/libprocess/3rdparty/stout/include/stout/protobuf.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/protobuf.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/protobuf.hpp
index 57d5fdf..dfb04fa 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/protobuf.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/protobuf.hpp
@@ -544,34 +544,88 @@ inline Try<Nothing> parse(
   return Nothing();
 }
 
-} // namespace internal {
-
 
+// Parses a single protobuf message of type T from a JSON::Object.
+// NOTE: This struct is used by the public parse<T>() function below. See
+// comments there for the reason why we opted for this design.
 template <typename T>
-Try<T> parse(const JSON::Value& value)
+struct Parse
 {
-  { google::protobuf::Message* message = (T*) NULL; (void) message; }
+  Try<T> operator()(const JSON::Value& value)
+  {
+    { google::protobuf::Message* message = (T*) NULL; (void) message; }
 
-  const JSON::Object* object = boost::get<JSON::Object>(&value);
+    const JSON::Object* object = boost::get<JSON::Object>(&value);
+    if (object == NULL) {
+      return Error("Expecting a JSON object");
+    }
 
-  if (object == NULL) {
-    return Error("Expecting a JSON object");
-  }
+    T message;
 
-  T message;
+    Try<Nothing> parse = internal::parse(&message, *object);
+    if (parse.isError()) {
+      return Error(parse.error());
+    }
 
-  Try<Nothing> parse = internal::parse(&message, *object);
+    if (!message.IsInitialized()) {
+      return Error("Missing required fields: " +
+                   message.InitializationErrorString());
+    }
 
-  if (parse.isError()) {
-    return Error(parse.error());
+    return message;
   }
+};
 
-  if (!message.IsInitialized()) {
-    return Error("Missing required fields: " +
-                 message.InitializationErrorString());
+
+// Partial specialization for RepeatedPtrField<T> to parse a sequence of
+// protobuf messages from a JSON::Array by repeatedly invoking Parse<T> to
+// facilitate conversions like JSON::Array -> Resources.
+// NOTE: This struct is used by the public parse<T>() function below. See
+// comments there for the reason why we opted for this design.
+template <typename T>
+struct Parse<google::protobuf::RepeatedPtrField<T>>
+{
+  Try<google::protobuf::RepeatedPtrField<T>> operator()(
+      const JSON::Value& value)
+  {
+    { google::protobuf::Message* message = (T*) NULL; (void) message; }
+
+    const JSON::Array* array = boost::get<JSON::Array>(&value);
+    if (array == NULL) {
+      return Error("Expecting a JSON array");
+    }
+
+    google::protobuf::RepeatedPtrField<T> collection;
+    collection.Reserve(static_cast<int>(array->values.size()));
+
+    // Parse messages one by one and propagate an error if it happens.
+    foreach (const JSON::Value& elem, array->values) {
+      Try<T> message = Parse<T>()(elem);
+      if (message.isError()) {
+        return Error(message.error());
+      }
+
+      collection.Add()->CopyFrom(message.get());
+    }
+
+    return collection;
   }
+};
+
+} // namespace internal {
 
-  return message;
+// A dispatch wrapper which parses protobuf messages(s) from a given JSON value.
+// We use partial specialization of
+//   - internal::Parse<T> for JSON::Object
+//   - internal::Parse<google::protobuf::RepeatedPtrField<T>> for JSON::Array
+// to determine whether T is a single message or a sequence of messages.
+// We cannot partially specialize function templates and overloaded function
+// approach combined with std::enable_if is not that clean, hence we leverage
+// partial specialization of class templates.
+template <typename T>
+Try<T> parse(const JSON::Value& value)
+{
+  return internal::Parse<T>()(value);
 }
 
 } // namespace protobuf {