chromium/third_party/mediapipe/src/mediapipe/framework/packet.h

// Copyright 2019 The MediaPipe Authors.
//
// Licensed 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.
//
// Defines Packet, a container capable of holding an object of any type.

#ifndef MEDIAPIPE_FRAMEWORK_PACKET_H_
#define MEDIAPIPE_FRAMEWORK_PACKET_H_

#include <cstddef>
#include <cstdint>
#include <memory>
#include <ostream>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

#include "absl/base/attributes.h"
#include "absl/base/macros.h"
#include "absl/base/optimization.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/absl_check.h"
#include "absl/log/absl_log.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/synchronization/mutex.h"
#include "google/protobuf/message.h"
#include "google/protobuf/message_lite.h"
#include "mediapipe/framework/deps/no_destructor.h"
#include "mediapipe/framework/deps/registration.h"
#include "mediapipe/framework/port.h"
#include "mediapipe/framework/port/canonical_errors.h"
#include "mediapipe/framework/port/logging.h"
#include "mediapipe/framework/port/proto_ns.h"
#include "mediapipe/framework/port/ret_check.h"
#include "mediapipe/framework/port/status.h"
#include "mediapipe/framework/port/status_builder.h"
#include "mediapipe/framework/port/status_macros.h"
#include "mediapipe/framework/port/statusor.h"
#include "mediapipe/framework/timestamp.h"
#include "mediapipe/framework/tool/type_util.h"
#include "mediapipe/framework/type_map.h"

namespace mediapipe {

class Packet;

namespace packet_internal {
class HolderBase;

Packet Create(HolderBase* holder);
Packet Create(HolderBase* holder, Timestamp timestamp);
Packet Create(std::shared_ptr<const HolderBase> holder, Timestamp timestamp);
const HolderBase* GetHolder(const Packet& packet);
const std::shared_ptr<const HolderBase>& GetHolderShared(const Packet& packet);
std::shared_ptr<const HolderBase> GetHolderShared(Packet&& packet);
absl::StatusOr<Packet> PacketFromDynamicProto(const std::string& type_name,
                                              const std::string& serialized);
}  // namespace packet_internal

// A generic container class which can hold data of any type.  The type of
// the data is specified when accessing the data (using Packet::Get<T>()).
//
// The Packet is implemented as a reference-counted pointer.  This means
// that copying Packets creates a fast, shallow copy.  Packets are
// copyable, movable, and assignable.  Packets can be stored in STL
// containers.  A Packet may optionally contain a timestamp.
//
// The preferred method of creating a Packet is with MakePacket<T>().
// The Packet typically owns the object that it contains, but
// PointToForeign allows a Packet to be constructed which does not
// own its data.
//
// This class is thread compatible.
class Packet {};

// Factory functions for creating Packets. Non-members as opposed to static
// methods, to prevent users from mistakenly calling them on Packet instances.

// Returns a Packet that adopts the object; the Packet assumes the ownership.
// The timestamp of the returned Packet is Timestamp::Unset(). To set the
// timestamp, the caller should do Adopt(...).At(...).
//
// Generally prefer MakePacket<T>().
template <typename T>
Packet Adopt(const T* ptr);

// Returns a Packet that does not own its data. The data pointed to by *ptr
// remains owned by the caller, who must ensure that it outlives not only the
// returned Packet but also all of its copies.
//
// Optionally, `cleanup` object can be specified to invoke when all copies of
// the packet are destroyed (can be used to capture the foreign owner if
// possible and ensure the lifetime).
//
// The timestamp of the returned Packet is Timestamp::Unset(). To set the
// timestamp, the caller should do PointToForeign(...).At(...).
template <typename T>
Packet PointToForeign(const T* ptr,
                      absl::AnyInvocable<void()> cleanup = nullptr);

// Adopts the data but places it in a std::unique_ptr inside the
// resulting Packet, leaving the timestamp unset. This allows the
// adopted data to be mutated, with the mutable data accessible as
// packet.Get<std::unique_ptr<T>>().get(). GetFromUniquePtr below provides
// a more syntactically-pleasing way of accomplishing that.
template <typename T>
Packet AdoptAsUniquePtr(T* ptr) {}

// A SyncedPacket is a packet containing a reference to another packet, and the
// reference can be updated.
// SyncedPacket is thread-safe.
class SyncedPacket {};

// Adopt the data as SyncedPacket, so that the content of the packet can be
// updated in a thread-safe way.
// Usage:
//   Packet synced_packet = AdoptAsSyncedPacket(new int(100));
//   Packet value_packet =
//       synced_packet.Get<std::unique_ptr<SyncedPacket>>()->Get();
//   EXPECT_EQ(100, value_packet.Get<int>());
//   // update the value.
//   Packet new_value_packet = Adopt(new int(999));
//   synced_packet.Get<std::unique_ptr<SyncedPacket>>()
//       ->UpdatePacket(new_value_packet);
//   Packet packet_new =
//       synced_packet.Get<std::unique_ptr<SyncedPacket>>()->Get();
//   EXPECT_EQ(999, packet_new.Get<int>());

template <typename T>
Packet AdoptAsSyncedPacket(const T* ptr) {}

// Create a packet containing an object of type T initialized with the
// provided arguments. Similar to MakeUnique. Especially convenient for arrays,
// since it ensures the packet gets the right type (see below).
//
// Version for scalars.
template <typename T,
          typename std::enable_if<!std::is_array<T>::value>::type* = nullptr,
          typename... Args>
Packet MakePacket(Args&&... args) {}

// Version for arrays. We have to use reinterpret_cast because new T[N]
// returns a T* instead of a T(*)[N] (i.e. a pointer to the first element
// instead of a pointer to the array itself - they have the same value, but
// different types), which would prevent Adopt from seeing the array's type
// if we did not have the cast.
template <typename T,
          typename std::enable_if<std::is_array<T>::value>::type* = nullptr,
          typename... Args>
Packet MakePacket(Args&&... args) {}

// Returns a mutable pointer to the data in a unique_ptr in a packet. This
// is useful in combination with AdoptAsUniquePtr.  The caller must
// exercise caution when mutating the retrieved data, since the data
// may be accessible from other locations.
template <typename T>
T* GetFromUniquePtr(const Packet& packet) {}

// Returns a shared_ptr to the payload of the packet which retains its object
// through a copy of the packet.
// Use std::const_pointer_cast if you need a shared_ptr<T>, but remember that
// you must not change the payload if the packet has other owners.
template <typename T>
ABSL_DEPRECATED("Use Packet::Share<T>() instead.")
std::shared_ptr<const T> SharedPtrWithPacket(const Packet& packet) {}

//// Implementation details.
namespace packet_internal {

template <typename T>
class Holder;
template <typename T>
class ForeignHolder;

class HolderBase {};

// Two helper functions to get the proto base pointers.
template <typename T>
const proto_ns::MessageLite* ConvertToProtoMessageLite(const T* data,
                                                       std::false_type) {}

template <typename T>
const proto_ns::MessageLite* ConvertToProtoMessageLite(const T* data,
                                                       std::true_type) {}

// Helper structs for determining if a type is an std::vector<Proto>.
template <typename Type>
struct is_proto_vector : public std::false_type {};

is_proto_vector<std::vector<ItemT, Allocator>>;

// Helper function to create and return a vector of pointers to proto message
// elements of the vector passed into the function.
template <typename T>
absl::StatusOr<std::vector<const proto_ns::MessageLite*>>
ConvertToVectorOfProtoMessageLitePtrs(const T* data,
                                      /*is_proto_vector=*/std::false_type) {}

template <typename T>
absl::StatusOr<std::vector<const proto_ns::MessageLite*>>
ConvertToVectorOfProtoMessageLitePtrs(const T* data,
                                      /*is_proto_vector=*/std::true_type) {}

// This registry is used to create Holders of the right concrete C++ type given
// a proto type string (which is used as the registration key).
class MessageHolderRegistry
    : public GlobalFactoryRegistry<std::unique_ptr<HolderBase>> {};

template <typename T>
struct is_concrete_proto_t
    : public std::integral_constant<
          bool, std::is_base_of<proto_ns::MessageLite, T>{};

template <typename T>
std::unique_ptr<HolderBase> CreateMessageHolder() {}

// Registers a message type. T must be a non-cv-qualified concrete proto type.
MEDIAPIPE_STATIC_REGISTRATOR_TEMPLATE()

// For non-Message payloads, this does nothing.
template <typename T, typename Enable = void>
struct HolderPayloadRegistrator {};

// This template ensures that, for each concrete MessageLite subclass that is
// stored in a Packet, we register a function that allows us to create a
// Holder with the correct payload type from the proto's type name.
//
// We must use std::remove_cv to ensure we don't try to register Foo twice if
// there are Holder<Foo> and Holder<const Foo>. TODO: lift this
// up to Holder?
template <typename T>
struct HolderPayloadRegistrator<
    T, typename std::enable_if<is_concrete_proto_t<T>{}>::type>
    : private MessageRegistrator<typename std::remove_cv<T>::type> {};

template <typename T>
class Holder : public HolderBase, private HolderPayloadRegistrator<T> {};

// Like Holder, but does not own its data.
template <typename T>
class ForeignHolder : public Holder<T> {};

template <typename T>
Holder<T>* HolderBase::AsMutable() const {}

template <typename T>
const Holder<T>* HolderBase::As() const {}

}  // namespace packet_internal

inline Packet::Packet(const Packet& packet)
    :{}

inline Packet& Packet::operator=(const Packet& packet) {}

template <typename T>
inline absl::StatusOr<std::unique_ptr<T>> Packet::Consume() {}

template <typename T>
inline absl::StatusOr<std::unique_ptr<T>> Packet::ConsumeOrCopy(
    bool* was_copied,
    typename std::enable_if<!std::is_array<T>::value>::type*) {}

template <typename T>
inline absl::StatusOr<std::unique_ptr<T>> Packet::ConsumeOrCopy(
    bool* was_copied,
    typename std::enable_if<std::is_array<T>::value &&
                            std::extent<T>::value != 0>::type*) {}

template <typename T>
inline absl::StatusOr<std::unique_ptr<T>> Packet::ConsumeOrCopy(
    bool* was_copied,
    typename std::enable_if<std::is_array<T>::value &&
                            std::extent<T>::value == 0>::type*) {}

inline Packet::Packet(Packet&& packet) {}

inline Packet& Packet::operator=(Packet&& packet) {}

inline bool Packet::IsEmpty() const {}

inline TypeId Packet::GetTypeId() const {}

template <typename T>
inline const T& Packet::Get() const {}

// Returns a shared pointer to the object of typename T if it contains
// one, an error otherwise (if the packet is empty or of another type). It is
// safe to concurrently call Share() on the same packet from multiple threads.
template <typename T>
inline absl::StatusOr<std::shared_ptr<const T>> Packet::Share() const {}

inline Timestamp Packet::Timestamp() const {}

template <typename T>
Packet Adopt(const T* ptr) {}

template <typename T>
Packet PointToForeign(const T* ptr, absl::AnyInvocable<void()> cleanup) {}

// Equal Packets refer to the same memory contents, like equal pointers.
inline bool operator==(const Packet& p1, const Packet& p2) {}
inline bool operator!=(const Packet& p1, const Packet& p2) {}

namespace packet_internal {

inline const std::shared_ptr<const HolderBase>& GetHolderShared(
    const Packet& packet) {}

inline std::shared_ptr<const HolderBase> GetHolderShared(Packet&& packet) {}

}  // namespace packet_internal

}  // namespace mediapipe

#endif  // MEDIAPIPE_FRAMEWORK_PACKET_H_