15#ifndef ACTIONENGINE_DATA_SERIALIZATION_H_ 
   16#define ACTIONENGINE_DATA_SERIALIZATION_H_ 
   23#include <absl/container/flat_hash_map.h> 
   29using Bytes = std::string;
 
   30using Serializer = std::function<absl::StatusOr<Bytes>(std::any)>;
 
   31using Deserializer = std::function<absl::StatusOr<std::any>(Bytes)>;
 
   33class SerializerRegistry {
 
   36  [[nodiscard]] absl::StatusOr<Bytes> Serialize(
 
   37      T value, std::string_view mimetype) 
const;
 
   39  [[nodiscard]] absl::StatusOr<std::any> Deserialize(
 
   40      Bytes data, std::string_view mimetype) 
const;
 
   47  [[nodiscard]] absl::StatusOr<T> DeserializeAs(
 
   48      const Bytes& data, std::string_view mimetype) 
const;
 
   50  void RegisterSerializer(std::string_view mimetype, Serializer serializer);
 
   52  void RegisterDeserializer(std::string_view mimetype,
 
   53                            Deserializer deserializer);
 
   55  [[nodiscard]] 
bool HasSerializers(std::string_view mimetype) 
const;
 
   57  [[nodiscard]] 
bool HasDeserializers(std::string_view mimetype) 
const;
 
   59  [[nodiscard]] 
void* GetUserData() 
const;
 
   61  void SetUserData(std::shared_ptr<void> user_data);
 
   64  absl::flat_hash_map<std::string, absl::InlinedVector<Serializer, 2>>
 
   66  absl::flat_hash_map<std::string, absl::InlinedVector<Deserializer, 2>>
 
   68  std::shared_ptr<void> user_data_ =
 
   73absl::StatusOr<Bytes> SerializerRegistry::Serialize(
 
   74    T value, std::string_view mimetype)
 const {
 
   75  if (mimetype.empty()) {
 
   76    return absl::InvalidArgumentError(
 
   77        "Serialize(value, mimetype) was called with an empty mimetype.");
 
   80  const auto it = mime_serializers_.find(mimetype);
 
   81  if (it == mime_serializers_.end()) {
 
   82    return absl::UnimplementedError(absl::StrFormat(
 
   83        "No serializer is registered for mimetype %v.", mimetype));
 
   86  for (
const auto& serializer : it->second | std::views::reverse) {
 
   88    auto result = serializer(std::move(value));
 
   90      return std::move(*result);
 
   94  return absl::UnimplementedError(
 
   95      absl::StrFormat(
"No serializer could handle value of type %s for " 
   97                      typeid(T).name(), mimetype));
 
  101absl::StatusOr<T> SerializerRegistry::DeserializeAs(
 
  102    const Bytes& data, std::string_view mimetype)
 const {
 
  103  auto deserialized = Deserialize(data, mimetype);
 
  104  if (!deserialized.ok()) {
 
  105    return deserialized.status();
 
  107  if (std::any_cast<T>(&*deserialized) == 
nullptr) {
 
  108    return absl::InvalidArgumentError(
 
  109        absl::StrFormat(
"Deserialized type does not match expected type %s.",
 
  112  return std::any_cast<T>(*std::move(deserialized));
 
  115void InitSerializerRegistryWithDefaults(SerializerRegistry* registry);
 
  117SerializerRegistry& GetGlobalSerializerRegistry();
 
  119inline SerializerRegistry* GetGlobalSerializerRegistryPtr() {
 
  120  return &GetGlobalSerializerRegistry();
 
  123void SetGlobalSerializerRegistry(
const SerializerRegistry& registry);
 
  126absl::StatusOr<Chunk> ToChunk(T value, std::string_view mimetype = {},
 
  127                              SerializerRegistry* 
const registry = 
nullptr) {
 
  128  if (mimetype.empty()) {
 
  129    return absl::FailedPreconditionError(absl::StrFormat(
 
  130        "Serialize(value, mimetype) was called with an empty mimetype, and " 
  131        "value's type %s is not a candidate for ADL-based conversion.",
 
  135  SerializerRegistry* resolved_registry =
 
  136      registry ? registry : GetGlobalSerializerRegistryPtr();
 
  138  auto data = resolved_registry->Serialize(std::move(value), mimetype);
 
  140    return data.status();
 
  143               .data = std::move(*data)};
 
  146template <ConvertibleToChunk T>
 
  147absl::StatusOr<Chunk> ToChunk(T value, std::string_view mimetype = {},
 
  148                              SerializerRegistry* 
const registry = 
nullptr) {
 
  149  if (mimetype.empty()) {
 
  150    return act::ConvertToOrDie<Chunk>(std::move(value));
 
  153  SerializerRegistry* resolved_registry =
 
  154      registry ? registry : GetGlobalSerializerRegistryPtr();
 
  156  auto data = resolved_registry->Serialize(std::move(value), mimetype);
 
  158    return data.status();
 
  161               .data = std::move(*data)};
 
  165absl::StatusOr<T> FromChunkAs(
Chunk chunk, std::string_view mimetype = {},
 
  166                              SerializerRegistry* 
const registry = 
nullptr)
 
  167    requires(ConvertibleFromChunk<T>) {
 
  168  if (mimetype.empty()) {
 
  169    return act::ConvertToOrDie<T>(std::move(chunk));
 
  172  if (!chunk.metadata) {
 
  173    chunk.metadata.emplace();
 
  176  if (chunk.metadata->mimetype.empty()) {
 
  177    chunk.metadata->mimetype = mimetype;
 
  178    return act::ConvertToOrDie<T>(std::move(chunk));
 
  181  const SerializerRegistry* resolved_registry =
 
  182      registry ? registry : GetGlobalSerializerRegistryPtr();
 
  184  return resolved_registry->DeserializeAs<T>(std::move(chunk).data, mimetype);
 
  187absl::StatusOr<std::any> FromChunk(
 
  188    Chunk chunk, std::string_view mimetype = {},
 
  189    const SerializerRegistry* registry = 
nullptr);
 
  192absl::StatusOr<T> FromChunkAs(
Chunk chunk, std::string_view mimetype = {},
 
  193                              SerializerRegistry* 
const registry = 
nullptr)
 
  194    requires(!ConvertibleFromChunk<T>) {
 
  195  if (mimetype.empty()) {
 
  196    return absl::FailedPreconditionError(
 
  197        "FromChunkAs(chunk, mimetype) was called with an empty mimetype, " 
  198        "and chunk's type is not a candidate for ADL-based conversion.");
 
  201  SerializerRegistry* resolved_registry =
 
  202      registry ? registry : GetGlobalSerializerRegistryPtr();
 
  204  return resolved_registry->DeserializeAs<T>(std::move(chunk), mimetype);
 
ActionEngine data structures used to implement actions and nodes (data streams).