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

// This file defines a typed Packet type. It fully interoperates with the older
// mediapipe::Packet; creating an api::Packet<T> that refers to an existing
// Packet (or vice versa) is cheap, just like copying a Packet. Ownership of
// the payload is shared. Consider this as a typed view into the same data.
//
// Conversion is currently done explicitly with the FromOldPacket and
// ToOldPacket functions, but calculator code does not need to concern itself
// with it.

#ifndef MEDIAPIPE_FRAMEWORK_API2_PACKET_H_
#define MEDIAPIPE_FRAMEWORK_API2_PACKET_H_

#include <memory>
#include <type_traits>
#include <utility>

#include "absl/base/attributes.h"
#include "absl/base/optimization.h"
#include "absl/log/absl_check.h"
#include "absl/meta/type_traits.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "mediapipe/framework/api2/tuple.h"
#include "mediapipe/framework/packet.h"
#include "mediapipe/framework/port/logging.h"
#include "mediapipe/framework/port/status_macros.h"
#include "mediapipe/framework/timestamp.h"

namespace mediapipe {
namespace api2 {

Timestamp;
HolderBase;

template <typename T>
class Packet;

struct AnyType {};

// Type-erased packet.
class PacketBase {};

PacketBase FromOldPacket(const mediapipe::Packet& op);
PacketBase FromOldPacket(mediapipe::Packet&& op);
mediapipe::Packet ToOldPacket(const PacketBase& p);
mediapipe::Packet ToOldPacket(PacketBase&& p);

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

template <class T>
absl::Status PacketBase::ValidateAsType() const {}

template <class T>
absl::StatusOr<std::shared_ptr<const T>> PacketBase::Share() const {}

// This is used to indicate that the packet could be holding one of a set of
// types, e.g. Packet<OneOf<A, B>>.
//
// A Packet<OneOf<T...>> has an interface similar to std::variant<T...>.
// However, we cannot use std::variant directly, since it requires that the
// contained object be stored in place within the variant.
// Suppose we have a stream that accepts an Image or an ImageFrame, and it
// receives a Packet<ImageFrame>. To present it as a
// std::variant<Image, ImageFrame> we would have to move the ImageFrame into
// the variant (or copy it), but that is not compatible with Packet's existing
// ownership model.
// We could have Get() return a std::variant<std::reference_wrapper<Image>,
// std::reference_wrapper<ImageFrame>>, but that would just make user code more
// convoluted.
//
// TODO: should we just use Packet<T...>?
template <class... T>
struct OneOf {};

namespace internal {

template <class T>
inline void CheckCompatibleType(const HolderBase& holder, internal::Wrap<T>) {}

template <class... T>
inline void CheckCompatibleType(const HolderBase& holder,
                                internal::Wrap<OneOf<T...>>) {}

// TODO: remove usage of internal::Generic and simply use AnyType.
Generic;

template <class V, class U>
struct IsCompatibleType : std::false_type {};
IsCompatibleType<V, V>;
IsCompatibleType<V, internal::Generic>;
IsCompatibleType<V, OneOf<U...>>;

}  // namespace internal

template <typename T>
inline Packet<T> PacketBase::As() const {}

template <>
inline Packet<internal::Generic> PacketBase::As<internal::Generic>() const;

template <typename T = internal::Generic>
class Packet;
#if __cplusplus >= 201703L
// Deduction guide to silence -Wctad-maybe-unsupported.
<deduction guide for Packet>();
#endif  // C++17

template <>
class Packet<internal::Generic> : public PacketBase {};

// Having Packet<T> subclass Packet<Generic> will require hiding some methods
// like As. May be better not to subclass, and allow implicit conversion
// instead.
template <typename T>
class Packet : public Packet<internal::Generic> {};

namespace internal {
template <class... F>
struct Overload : F... {};
template <class... F>
explicit Overload(F...) -> Overload<F...>;

template <class T, class... U>
struct First {};

template <class T>
struct AddStatus {};
AddStatus<absl::StatusOr<T>>;
template <>
struct AddStatus<absl::Status> {};
template <>
struct AddStatus<void> {};

template <class R, class F, class... A>
struct CallAndAddStatusImpl {};
CallAndAddStatusImpl<void, F, A...>;

template <class F, class... A>
auto CallAndAddStatus(const F& f, A&&... a) {}

}  // namespace internal

Packet<OneOf<T...>>;

template <>
inline Packet<internal::Generic> PacketBase::As<internal::Generic>() const {}

inline PacketBase PacketBase::At(Timestamp timestamp) const& {}

inline PacketBase PacketBase::At(Timestamp timestamp) && {}

template <typename T>
inline Packet<T> Packet<T>::At(Timestamp timestamp) const& {}

template <typename T>
inline Packet<T> Packet<T>::At(Timestamp timestamp) && {}

inline Packet<internal::Generic> Packet<internal::Generic>::At(
    Timestamp timestamp) const& {}

inline Packet<internal::Generic> Packet<internal::Generic>::At(
    Timestamp timestamp) && {}

template <typename T, typename... Args>
Packet<T> MakePacket(Args&&... args) {}

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

template <typename T>
Packet<T> PacketAdopting(std::unique_ptr<T> ptr) {}

}  // namespace api2
}  // namespace mediapipe

#endif  // MEDIAPIPE_FRAMEWORK_API2_PACKET_H_