33#if PARCEL_HAS_EXPECTED
88 std::map<std::string, cell_type_descriptor_t, std::less<>>
referenced;
95 json_t refs = json_t::object();
97 refs[k] = d->to_json();
100 {
"root",
root->to_json()},
101 {
"referenced", std::move(refs)},
116 std::map<std::string, cell_type_descriptor_t, std::less<>> by_kind_;
143 template <
typename... Ds>
159 template <
typename... Cs>
180#if PARCEL_HAS_EXPECTED
194 [[nodiscard]] std::expected<cell_t, ParcelError> try_cell_from_json(
json_t const& j)
const;
202 [[nodiscard]] std::expected<cell_t, ParcelError> try_cell_from_string(std::string_view s)
const;
206 [[nodiscard]] std::vector<cell_type_descriptor_t>
all()
const;
209 [[nodiscard]] std::vector<std::string_view>
kinds()
const;
212 [[nodiscard]] std::size_t
count() const noexcept;
218 [[nodiscard]]
bool contains(std::string_view kind) const;
237 template <typename T>
254 throw std::runtime_error(
"ParcelRegistry::register_kind: null descriptor");
256 by_kind_.insert_or_assign(std::string(d->kind()), std::move(d));
260 if (
const auto it = by_kind_.find(kind); it != by_kind_.end()) {
267 if (!j.is_object()) {
271 if (it_k == j.end() || !it_k->is_string()) {
274 const auto kind = it_k->get<std::string_view>();
275 const auto desc =
find(kind);
276 if (desc ==
nullptr) {
278 std::string(kind) +
"'",
281 return desc->cell_from_json(j, *
this);
284#if PARCEL_HAS_EXPECTED
285inline std::expected<cell_t, ParcelError>
286ParcelRegistry::try_cell_from_json(
json_t const& j)
const {
287 if (!j.is_object()) {
288 return std::unexpected(
292 if (it_k == j.end() || !it_k->is_string()) {
293 return std::unexpected(
296 const auto kind = it_k->get<std::string_view>();
297 const auto desc =
find(kind);
298 if (desc ==
nullptr) {
299 return std::unexpected(
303 return desc->cell_from_json(j, *
this);
304 }
catch (ParcelException
const& e) {
308 auto err = e.to_error();
309 if (err.kind.empty()) {
310 err.kind = std::string(kind);
312 return std::unexpected(std::move(err));
313 }
catch (std::exception
const& e) {
314 return std::unexpected(
322inline std::expected<cell_t, ParcelError>
323ParcelRegistry::try_cell_from_string(std::string_view s)
const {
326 j = json_t::parse(s);
327 }
catch (std::exception
const& e) {
330 return std::unexpected(
333 return try_cell_from_json(j);
338 std::vector<cell_type_descriptor_t> out;
339 out.reserve(by_kind_.size());
340 for (
const auto& d : by_kind_ | std::views::values) {
347 std::vector<std::string_view> out;
348 out.reserve(by_kind_.size());
349 for (
const auto& d : by_kind_ | std::views::values) {
350 out.push_back(d->kind());
356 return by_kind_.size();
360 return by_kind_.contains(kind);
363inline std::vector<cell_type_descriptor_t>
365 std::vector<cell_type_descriptor_t> out;
366 for (
const auto& d : by_kind_ | std::views::values) {
367 if (d->category() == c) {
374inline std::vector<cell_type_descriptor_t>
376 std::vector<cell_type_descriptor_t> out;
377 for (
const auto& d : by_kind_ | std::views::values) {
378 if (d->storage_type() == ti) {
386 const auto root =
find(kind);
387 if (root ==
nullptr) {
389 "ParcelRegistry::define: unknown kind '" + std::string(kind) +
"'", std::string(kind));
392 std::vector<std::string_view> queue;
395 if (
auto const* st =
dynamic_cast<ISubTypes const*
>(d.get()); st !=
nullptr) {
396 for (
auto sk : st->sub_kinds()) {
403 while (!queue.empty()) {
404 auto k = queue.back();
406 if (k == root->kind()) {
409 if (out.referenced.contains(k)) {
415 "ParcelRegistry::define: kind '" + std::string(root->kind()) +
416 "' references unregistered kind '" + std::string(k) +
"'",
419 out.referenced.emplace(std::string(k), d);
Core ICell interface, cell_t handle, BaseCell CRTP base, and CellLike concept.
std::shared_ptr< ICellTypeDescriptor > cell_type_descriptor_t
Shared handle to a runtime cell-type descriptor.
Definition cell.h:63
std::shared_ptr< ICell > cell_t
Shared handle to any ICell-derived value — the canonical cell pointer.
Definition cell.h:68
JSON shape was wrong (missing/non-string k, missing v, etc.).
Definition error.h:158
Runtime catalog of cell-type descriptors, keyed by wire kind id.
Definition registry.h:115
Definition define(std::string_view kind) const
Build a Definition rooted at kind plus everything it references.
Definition registry.h:385
std::vector< cell_type_descriptor_t > all() const
Every registered descriptor.
Definition registry.h:337
void register_kind(cell_type_descriptor_t d)
Register or replace a descriptor by its kind id.
Definition registry.h:252
ParcelRegistry & register_kinds(Ds &&... ds)
Variadic shorthand: register many descriptors in one call.
Definition registry.h:144
std::size_t count() const noexcept
Number of registered kinds.
Definition registry.h:355
std::vector< std::string_view > kinds() const
Every registered kind id.
Definition registry.h:346
bool contains(std::string_view kind) const
Whether kind is registered.
Definition registry.h:359
std::vector< cell_type_descriptor_t > find_by_category(descriptor::CellCategory c) const
Every descriptor whose category() matches c.
Definition registry.h:364
cell_type_descriptor_t find(std::string_view kind) const
Look up a descriptor by kind id.
Definition registry.h:259
cell_t cell_from_json(json_t const &j) const
Deserialize any registered cell from JSON, dispatching by "k".
Definition registry.h:266
ParcelRegistry & register_cells()
Variadic shorthand: register one descriptor per cell type.
Definition registry.h:160
std::vector< cell_type_descriptor_t > find_by_storage() const
Every descriptor whose storage type is T.
Definition registry.h:238
Registry was asked to dispatch a kind it does not know.
Definition error.h:175
Runtime cell-type descriptors and the schema-graph mix-ins (IHasFields, ISubTypes).
CellCategory
Coarse runtime classification of a cell type.
Definition descriptor.h:35
ParcelError and the non-throwing surface that returns std::expected.
nlohmann::json typedef shared across cell types.
nlohmann::json json_t
Project-wide alias for nlohmann::json.
Definition json.h:19
Toggles for the built-in cell registrations performed by register_builtins.
Definition registry.h:50
bool ulid
Register UlidCell (only takes effect when the ULID dependency is enabled — PARCEL_HAS_ULID; an inert ...
Definition registry.h:75
bool commons
Register the commons cells: ColorCell, IconCell, DisplayInfoCell, FlagCell, FlagSetCell,...
Definition registry.h:70
bool typed_collections
Register TypedListCell<P>, TypedMapCell<P>, and TypedHashMapCell<P> for every primitive P.
Definition registry.h:59
bool collections
Register ListCell, MapCell, and HashMapCell (heterogeneous).
Definition registry.h:54
bool primitives
Register every PrimitiveCell<T>.
Definition registry.h:52
bool std
Register the std-adapter cells: SystemTimePointCell, UnixMillisCell, DurationMsCell,...
Definition registry.h:64
Closed-over schema for a single root kind plus everything it references.
Definition registry.h:84
json_t to_json() const
Serialize to a JSON object with root and referenced blocks.
Definition registry.h:94
std::map< std::string, cell_type_descriptor_t, std::less<> > referenced
Every kind transitively referenced by root, keyed by kind id.
Definition registry.h:88
cell_type_descriptor_t root
Descriptor for the requested root kind.
Definition registry.h:86
static constexpr std::string_view KEY_KIND
JSON key for the kind id ("k").
Definition cell.h:86
Mix-in declaring a descriptor refers to other registered cell kinds.
Definition descriptor.h:148
static ParcelError make(const Code c, std::string msg, std::string kind_id={}, std::string fld={})
Construct from code, message, and optional kind/field tags.
Definition error.h:107
@ TypeError
A typed value (e.g.
@ InvalidJson
Input was not parseable JSON or had wrong shape.
@ UnknownKind
JSON "k" referenced a kind not registered.