A11 (C++ runtime)
Native C++ implementation of the A11 streaming action runtime
Loading...
Searching...
No Matches
serializable.h
Go to the documentation of this file.
1/*
2 * Copyright 2026 The A11 Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
58#ifndef A11_DATA_SERIALIZABLE_H_
59#define A11_DATA_SERIALIZABLE_H_
60
61#include <cstdint>
62#include <string>
63#include <string_view>
64#include <utility>
65#include <vector>
66
67#include <absl/status/status.h>
68#include <absl/status/status_macros.h>
69#include <absl/status/statusor.h>
70#include <absl/strings/str_cat.h>
71#include <nlohmann/json.hpp>
72
75#include "a11/data/types.h"
76#include "a11/json_codec.h"
77
78namespace a11::data {
79
85template <typename T>
86struct TypeTag {};
87
88// The runtime's own types answer the same customization point every other
89// serializable type does, with the canonical tags from a11/data/serial_tags.h.
90inline std::string_view A11SerialTag(TypeTag<ChunkMetadata>) {
91 return kChunkMetadataTag;
92}
93
94inline std::string_view A11SerialTag(TypeTag<Chunk>) {
95 return kChunkTag;
96}
97
98inline std::string_view A11SerialTag(TypeTag<NodeRef>) {
99 return kNodeRefTag;
100}
101
102inline std::string_view A11SerialTag(TypeTag<NodeFragment>) {
103 return kNodeFragmentTag;
104}
105
106inline std::string_view A11SerialTag(TypeTag<Port>) {
107 return kPortTag;
108}
109
110inline std::string_view A11SerialTag(TypeTag<ActionMessage>) {
111 return kActionMessageTag;
112}
113
114inline std::string_view A11SerialTag(TypeTag<WireMessage>) {
115 return kWireMessageTag;
116}
117
118namespace serializable_internal {
119
120// Unqualified calls so ADL locates the customization points in T's namespace.
121
122template <typename T>
123concept HasSerialTag = requires {
124 {A11SerialTag(TypeTag<T>{})}->std::convertible_to<std::string_view>;
125};
126
127template <typename T>
128concept HasJson = requires(const T& value, const nlohmann::json& json) {
129 {A11ToJson(value)}->std::same_as<absl::StatusOr<nlohmann::json>>;
130 {A11FromJson(TypeTag<T>{}, json)}->std::same_as<absl::StatusOr<T>>;
131};
132
133template <typename T>
134concept HasMsgpackBytes = requires(const T& value, std::string_view bytes) {
135 {A11ToMsgpackBytes(value)}->std::same_as<absl::StatusOr<std::string>>;
136 {A11FromMsgpackBytes(TypeTag<T>{}, bytes)}->std::same_as<absl::StatusOr<T>>;
137};
138
139template <typename T>
140std::string SerialTag() {
141 return std::string(A11SerialTag(TypeTag<T>{}));
142}
143
144} // namespace serializable_internal
145
147template <typename T>
150
155template <typename T>
159
161template <typename T>
163
170template <typename T>
172
173template <typename T>
175 return serializable_internal::SerialTag<T>();
176}
177
182template <typename T>
184 SerializationRegistry& registry) {
185 return registry.Register<T>(
186 serializable_internal::SerialTag<T>(), std::string(kJsonMimetype),
187 [](const T& value) -> absl::StatusOr<Chunk> {
188 ABSL_ASSIGN_OR_RETURN(nlohmann::json json, A11ToJson(value));
189 ABSL_ASSIGN_OR_RETURN(std::string encoded, DumpJson(json, "JSON"));
190 return Chunk{.data = std::move(encoded)};
191 },
192 [](const Chunk& chunk) -> absl::StatusOr<T> {
193 ABSL_ASSIGN_OR_RETURN(const nlohmann::json json,
194 ParseJson(chunk.data, "JSON data"));
195 return A11FromJson(TypeTag<T>{}, json);
196 });
197}
198
204template <typename T>
206 SerializationRegistry& registry) {
208 return registry.Register<T>(
209 serializable_internal::SerialTag<T>(), std::string(kMsgpackMimetype),
210 [](const T& value) -> absl::StatusOr<Chunk> {
211 ABSL_ASSIGN_OR_RETURN(std::string bytes, A11ToMsgpackBytes(value));
212 return Chunk{.data = std::move(bytes)};
213 },
214 [](const Chunk& chunk) -> absl::StatusOr<T> {
215 return A11FromMsgpackBytes(TypeTag<T>{}, chunk.data);
216 });
217 } else {
218 // Derive MessagePack from the JSON representation.
219 return registry.Register<T>(
220 serializable_internal::SerialTag<T>(), std::string(kMsgpackMimetype),
221 [](const T& value) -> absl::StatusOr<Chunk> {
222 ABSL_ASSIGN_OR_RETURN(nlohmann::json json, A11ToJson(value));
223 ABSL_ASSIGN_OR_RETURN(std::string encoded, PackMsgpack(json, "JSON"));
224 return Chunk{.data = std::move(encoded)};
225 },
226 [](const Chunk& chunk) -> absl::StatusOr<T> {
227 ABSL_ASSIGN_OR_RETURN(const nlohmann::json json,
228 UnpackMsgpack(chunk.data, "JSON"));
229 return A11FromJson(TypeTag<T>{}, json);
230 });
231 }
232}
233
243template <typename T>
245 SerializationRegistry& registry, bool json = true, bool msgpack = true) {
246 if (json && JsonSerializable<T>) {
247 if constexpr (JsonSerializable<T>) {
248 ABSL_RETURN_IF_ERROR(RegisterJsonSerializable<T>(registry));
249 }
250 }
251 if (msgpack && MsgpackSerializable<T>) {
252 if constexpr (MsgpackSerializable<T>) {
253 ABSL_RETURN_IF_ERROR(RegisterMsgpackSerializable<T>(registry));
254 }
255 }
256 return absl::OkStatus();
257}
258
259} // namespace a11::data
260
261#endif // A11_DATA_SERIALIZABLE_H_
Definition serialization.h:161
absl::Status Register(const std::string &type_name, const std::string &mimetype, Serializer< T > serializer, Deserializer< T > deserializer)
Atomically registers a serializer/deserializer pair for T.
Definition serialization.h:268
Whether T publishes a serialisation tag.
Definition serializable.h:171
Whether T provides an ADL JSON representation.
Definition serializable.h:148
Whether T can be serialized to MessagePack, either directly via A11ToMsgpackBytes / A11FromMsgpackByt...
Definition serializable.h:156
Whether T supports at least one representation.
Definition serializable.h:162
Definition serializable.h:128
std::string value
Definition discover.cc:114
The only place A11 hands text or bytes to nlohmann, or asks for them.
std::string SerialTag()
Definition serializable.h:140
Definition json.cc:35
constexpr std::string_view kJsonMimetype
Media type of the built-in JSON codec.
Definition serialization.h:62
constexpr std::string_view kChunkTag
Definition serial_tags.h:62
constexpr std::string_view kChunkMetadataTag
Definition serial_tags.h:61
std::string_view A11SerialTag(TypeTag< ChunkMetadata >)
Definition serializable.h:90
constexpr std::string_view kPortTag
Definition serial_tags.h:65
constexpr std::string_view kMsgpackMimetype
Media type of the built-in MessagePack codec.
Definition serialization.h:64
constexpr std::string_view kActionMessageTag
Definition serial_tags.h:66
constexpr std::string_view kNodeRefTag
Definition serial_tags.h:63
std::string SerialTypeTag()
Definition serializable.h:174
absl::Status RegisterSerializable(SerializationRegistry &registry, bool json=true, bool msgpack=true)
Registers every representation T supports into registry.
Definition serializable.h:244
absl::Status RegisterJsonSerializable(SerializationRegistry &registry)
Registers a JSON codec (media type application/json) for T.
Definition serializable.h:183
absl::Status RegisterMsgpackSerializable(SerializationRegistry &registry)
Registers a MessagePack codec (media type application/x-msgpack) for T, using direct bytes when avail...
Definition serializable.h:205
constexpr std::string_view kWireMessageTag
Definition serial_tags.h:67
constexpr std::string_view kNodeFragmentTag
Definition serial_tags.h:64
absl::StatusOr< Json > ParseJson(std::string_view encoded, std::string_view what)
Parses JSON text, or explains why it is not JSON.
Definition json_codec.cc:342
absl::StatusOr< Json > UnpackMsgpack(std::string_view encoded, std::string_view what)
Decodes MessagePack bytes, or explains why they are not.
Definition json_codec.cc:437
absl::StatusOr< std::string > DumpJson(const Json &value, std::string_view what)
Definition json_codec.cc:387
absl::StatusOr< std::string > PackMsgpack(const Json &value, std::string_view what)
Definition json_codec.cc:418
The canonical cross-language serialization tags.
Type-and-mimetype indexed serialization of values to/from Chunks.
A unit of data: bytes plus optional descriptive metadata.
Definition types.h:185
Bytes data
Inline byte payload.
Definition types.h:188
Empty tag carrying a type T so customization points are found by argument-dependent lookup even when ...
Definition serializable.h:86
A11's core wire value types: chunks, node fragments and messages.