text: // Licensed to the Apache Software Foundation (ASF) under one
  // or more contributor license agreements.  See the NOTICE file
  // distributed with this work for additional information
  // regarding copyright ownership.  The ASF licenses this file
  // to you under the Apache License, Version 2.0 (the
  // "License"); you may not use this file except in compliance
  // with the License.  You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  #ifndef __MESOS_V1_HPP__
  #define __MESOS_V1_HPP__
  
  #include <iosfwd>
  #include <string>
  #include <vector>
  
  #include <boost/functional/hash.hpp>
  
  #include <google/protobuf/repeated_field.h>
  
  #include <mesos/v1/mesos.pb.h> // ONLY USEFUL AFTER RUNNING PROTOC.
  
  #include <stout/strings.hpp>
  
  // This file includes definitions for operators on public protobuf
  // classes (defined in mesos.proto, module.proto, etc.) that don't
  // have these operators generated by the protobuf compiler. The
  // corresponding definitions are in src/v1/type_utils.cpp.
  //
  // Mesos modules need some of the protobuf classes defined in
  // mesos.proto, module.proto, etc., and require some of these
  // operators declared in mesos.hpp. Exposing mesos.hpp
  // allows us to build modules without having a dependency on mesos
  // source tree (src/*).
  
  namespace mesos {
  namespace v1 {
  
  bool operator==(const CommandInfo& left, const CommandInfo& right);
  bool operator==(const CommandInfo::URI& left, const CommandInfo::URI& right);
  bool operator==(const Credential& left, const Credential& right);
  bool operator==(const DiscoveryInfo& left, const DiscoveryInfo& right);
  bool operator==(const Environment& left, const Environment& right);
  bool operator==(const ExecutorInfo& left, const ExecutorInfo& right);
  bool operator==(const Label& left, const Label& right);
  bool operator==(const Labels& left, const Labels& right);
  bool operator==(const MasterInfo& left, const MasterInfo& right);
  
  bool operator==(
      const ResourceStatistics& left,
      const ResourceStatistics& right);
  
  bool operator==(const AgentInfo& left, const AgentInfo& right);
  bool operator==(const TaskStatus& left, const TaskStatus& right);
  bool operator==(const URL& left, const URL& right);
  bool operator==(const Volume& left, const Volume& right);
  
  bool operator!=(const Labels& left, const Labels& right);
  bool operator!=(const TaskStatus& left, const TaskStatus& right);
  
  
  inline bool operator==(const ContainerID& left, const ContainerID& right)
  {
    return left.value() == right.value();
  }
  
  
  inline bool operator==(const ExecutorID& left, const ExecutorID& right)
  {
    return left.value() == right.value();
  }
  
  
  inline bool operator==(const FrameworkID& left, const FrameworkID& right)
  {
    return left.value() == right.value();
  }
  
  
  inline bool operator==(const FrameworkInfo& left, const FrameworkInfo& right)
  {
    return (left.name() == right.name()) && (left.user() == right.user());
  }
  
  
  inline bool operator==(const OfferID& left, const OfferID& right)
  {
    return left.value() == right.value();
  }
  
  
  inline bool operator==(const AgentID& left, const AgentID& right)
  {
    return left.value() == right.value();
  }
  
  
  inline bool operator==(const TaskID& left, const TaskID& right)
  {
    return left.value() == right.value();
  }
  
  
  inline bool operator==(const TimeInfo& left, const TimeInfo& right)
  {
    return left.nanoseconds() == right.nanoseconds();
  }
  
  
  inline bool operator==(const DurationInfo& left, const DurationInfo& right)
  {
    return left.nanoseconds() == right.nanoseconds();
  }
  
  
  inline bool operator==(const ContainerID& left, const std::string& right)
  {
    return left.value() == right;
  }
  
  
  inline bool operator==(const ExecutorID& left, const std::string& right)
  {
    return left.value() == right;
  }
  
  
  inline bool operator==(const FrameworkID& left, const std::string& right)
  {
    return left.value() == right;
  }
  
  
  inline bool operator==(const OfferID& left, const std::string& right)
  {
    return left.value() == right;
  }
  
  
  inline bool operator==(const AgentID& left, const std::string& right)
  {
    return left.value() == right;
  }
  
  
  inline bool operator==(const TaskID& left, const std::string& right)
  {
    return left.value() == right;
  }
  
  
  /**
   * For machines to match, both the `hostname` and `ip` must be equivalent.
   * Hostname is not case sensitive, so it is lowercased before comparison.
   */
  inline bool operator==(const MachineID& left, const MachineID& right)
  {
    // NOTE: Both fields default to the empty string if they are not specified,
    // so the string comparisons are safe.
    return left.has_hostname() == right.has_hostname() &&
      strings::lower(left.hostname()) == strings::lower(right.hostname()) &&
      left.has_ip() == right.has_ip() &&
      left.ip() == right.ip();
  }
  
  
  inline bool operator!=(const ContainerID& left, const ContainerID& right)
  {
    return left.value() != right.value();
  }
  
  
  inline bool operator!=(const ExecutorID& left, const ExecutorID& right)
  {
    return left.value() != right.value();
  }
  
  
  inline bool operator!=(const FrameworkID& left, const FrameworkID& right)
  {
    return left.value() != right.value();
  }
  
  
  inline bool operator!=(const AgentID& left, const AgentID& right)
  {
    return left.value() != right.value();
  }
  
  
  inline bool operator!=(const TimeInfo& left, const TimeInfo& right)
  {
    return !(left == right);
  }
  
  
  inline bool operator!=(const DurationInfo& left, const DurationInfo& right)
  {
    return !(left == right);
  }
  
  
  inline bool operator<(const ContainerID& left, const ContainerID& right)
  {
    return left.value() < right.value();
  }
  
  
  inline bool operator<(const ExecutorID& left, const ExecutorID& right)
  {
    return left.value() < right.value();
  }
  
  
  inline bool operator<(const FrameworkID& left, const FrameworkID& right)
  {
    return left.value() < right.value();
  }
  
  
  inline bool operator<(const OfferID& left, const OfferID& right)
  {
    return left.value() < right.value();
  }
  
  
  inline bool operator<(const AgentID& left, const AgentID& right)
  {
    return left.value() < right.value();
  }
  
  
  inline bool operator<(const TaskID& left, const TaskID& right)
  {
    return left.value() < right.value();
  }
  
  
  std::ostream& operator<<(std::ostream& stream, const ContainerID& containerId);
  
  
  std::ostream& operator<<(
      std::ostream& stream,
      const ContainerInfo& containerInfo);
  
  
  std::ostream& operator<<(std::ostream& stream, const ExecutorID& executorId);
  
  
  std::ostream& operator<<(std::ostream& stream, const ExecutorInfo& executor);
  
  
  std::ostream& operator<<(std::ostream& stream, const FrameworkID& frameworkId);
  
  
  std::ostream& operator<<(std::ostream& stream, const MasterInfo& master);
  
  
  std::ostream& operator<<(std::ostream& stream, const OfferID& offerId);
  
  
  std::ostream& operator<<(std::ostream& stream, const RateLimits& limits);
  
  
  std::ostream& operator<<(std::ostream& stream, const AgentID& agentId);
  
  
  std::ostream& operator<<(std::ostream& stream, const AgentInfo& agent);
  
  
  std::ostream& operator<<(std::ostream& stream, const TaskID& taskId);
  
  
  std::ostream& operator<<(std::ostream& stream, const MachineID& machineId);
  
  
  std::ostream& operator<<(std::ostream& stream, const TaskInfo& task);
  
  
  std::ostream& operator<<(std::ostream& stream, const TaskState& state);
  
  
  std::ostream& operator<<(
      std::ostream& stream,
      const std::vector<TaskID>& taskIds);
  
  
  std::ostream& operator<<(
      std::ostream& stream,
      const FrameworkInfo::Capability& capability);
  
  
  std::ostream& operator<<(std::ostream& stream, const Image::Type& imageType);
  
  
  template <typename T>
  inline std::ostream& operator<<(
      std::ostream& stream,
      const google::protobuf::RepeatedPtrField<T>& messages)
  {
    stream << "[ ";
    for (auto it = messages.begin(); it != messages.end(); ++it) {
      if (it != messages.begin()) {
        stream << ", ";
      }
      stream << *it;
    }
    stream << " ]";
    return stream;
  }
  
  
  std::ostream& operator<<(
      std::ostream& stream,
      const hashmap<std::string, std::string>& map);
  
  } // namespace v1 {
  } // namespace mesos {
  
  namespace std {
  
  template <>
  struct hash<mesos::v1::CommandInfo::URI>
  {
    typedef size_t result_type;
  
    typedef mesos::v1::CommandInfo::URI argument_type;
  
    result_type operator()(const argument_type& uri) const
    {
      size_t seed = 0;
  
      if (uri.extract()) {
        seed += 11;
      }
  
      if (uri.executable()) {
        seed += 2003;
      }
  
      boost::hash_combine(seed, uri.value());
      return seed;
    }
  };
  
  
  template <>
  struct hash<mesos::v1::ContainerID>
  {
    typedef size_t result_type;
  
    typedef mesos::v1::ContainerID argument_type;
  
    result_type operator()(const argument_type& containerId) const
    {
      size_t seed = 0;
      boost::hash_combine(seed, containerId.value());
      return seed;
    }
  };
  
  
  template <>
  struct hash<mesos::v1::ExecutorID>
  {
    typedef size_t result_type;
  
    typedef mesos::v1::ExecutorID argument_type;
  
    result_type operator()(const argument_type& executorId) const
    {
      size_t seed = 0;
      boost::hash_combine(seed, executorId.value());
      return seed;
    }
  };
  
  
  template <>
  struct hash<mesos::v1::FrameworkID>
  {
    typedef size_t result_type;
  
    typedef mesos::v1::FrameworkID argument_type;
  
    result_type operator()(const argument_type& frameworkId) const
    {
      size_t seed = 0;
      boost::hash_combine(seed, frameworkId.value());
      return seed;
    }
  };
  
  
  template <>
  struct hash<mesos::v1::OfferID>
  {
    typedef size_t result_type;
  
    typedef mesos::v1::OfferID argument_type;
  
    result_type operator()(const argument_type& offerId) const
    {
      size_t seed = 0;
      boost::hash_combine(seed, offerId.value());
      return seed;
    }
  };
  
  
  template <>
  struct hash<mesos::v1::AgentID>
  {
    typedef size_t result_type;
  
    typedef mesos::v1::AgentID argument_type;
  
    result_type operator()(const argument_type& agentId) const
    {
      size_t seed = 0;
      boost::hash_combine(seed, agentId.value());
      return seed;
    }
  };
  
  
  template <>
  struct hash<mesos::v1::TaskID>
  {
    typedef size_t result_type;
  
    typedef mesos::v1::TaskID argument_type;
  
    result_type operator()(const argument_type& taskId) const
    {
      size_t seed = 0;
      boost::hash_combine(seed, taskId.value());
      return seed;
    }
  };
  
  
  template <>
  struct hash<mesos::v1::TaskState>
  {
    typedef size_t result_type;
  
    typedef mesos::v1::TaskState argument_type;
  
    result_type operator()(const argument_type& taskState) const
    {
      // Use the underlying type of the enum as hash value.
      return static_cast<size_t>(taskState);
    }
  };
  
  
  template <>
  struct hash<mesos::v1::TaskStatus_Source>
  {
    typedef size_t result_type;
  
    typedef mesos::v1::TaskStatus_Source argument_type;
  
    result_type operator()(const argument_type& source) const
    {
      // Use the underlying type of the enum as hash value.
      return static_cast<size_t>(source);
    }
  };
  
  
  template <>
  struct hash<mesos::v1::TaskStatus_Reason>
  {
    typedef size_t result_type;
  
    typedef mesos::v1::TaskStatus_Reason argument_type;
  
    result_type operator()(const argument_type& reason) const
    {
      // Use the underlying type of the enum as hash value.
      return static_cast<size_t>(reason);
    }
  };
  
  
  template <>
  struct hash<mesos::v1::Image::Type>
  {
    typedef size_t result_type;
  
    typedef mesos::v1::Image::Type argument_type;
  
    result_type operator()(const argument_type& imageType) const
    {
      // Use the underlying type of the enum as hash value.
      return static_cast<size_t>(imageType);
    }
  };
  
  
  template <>
  struct hash<std::pair<mesos::v1::FrameworkID, mesos::v1::ExecutorID>>
  {
    typedef size_t result_type;
  
    typedef std::pair<
        mesos::v1::FrameworkID, mesos::v1::ExecutorID> argument_type;
  
    result_type operator()(const argument_type& pair) const
    {
      size_t seed = 0;
      boost::hash_combine(seed, std::hash<mesos::v1::FrameworkID>()(pair.first));
      boost::hash_combine(seed, std::hash<mesos::v1::ExecutorID>()(pair.second));
      return seed;
    }
  };
  
  
  template <>
  struct hash<mesos::v1::MachineID>
  {
    typedef size_t result_type;
  
    typedef mesos::v1::MachineID argument_type;
  
    result_type operator()(const argument_type& machineId) const
    {
      size_t seed = 0;
      boost::hash_combine(seed, strings::lower(machineId.hostname()));
      boost::hash_combine(seed, machineId.ip());
      return seed;
    }
  };
  
  } // namespace std {
  
  #endif // __MESOS_V1_HPP__
  