31#if PARCEL_HAS_EXPECTED
37struct ICellTypeDescriptor;
41struct is_std_variant : std::false_type {};
42template <
typename... Ts>
43struct is_std_variant<std::variant<Ts...>> : std::true_type {};
52struct disables_basecell_compare : std::false_type {};
56inline constexpr bool is_std_variant_v = detail::is_std_variant<std::remove_cvref_t<T>>::value;
59inline constexpr bool disables_basecell_compare_v =
60 detail::disables_basecell_compare<std::remove_cvref_t<T>>::value;
68using cell_t = std::shared_ptr<ICell>;
86 static constexpr std::string_view
KEY_KIND =
"k";
92 virtual ~ICell() =
default;
98 [[nodiscard]]
virtual std::string_view
kind()
const = 0;
116 [[nodiscard]]
virtual std::string
to_string()
const = 0;
145 [[nodiscard]]
virtual std::partial_ordering
compare(
ICell const& other)
const = 0;
157 [[nodiscard]]
virtual std::size_t
hash_value() const noexcept {
158 const std::size_t hk = std::hash<std::string_view>{}(this->
kind());
160 const auto j = this->
to_json();
162 const std::size_t hv =
163 (it != j.end()) ? std::hash<std::string>{}(it->dump()) : std::size_t{0};
164 return hk ^ (hv + 0x9e3779b97f4a7c15ULL + (hk << 6) + (hk >> 2));
172 return a.
compare(b) == std::partial_ordering::equivalent;
190 c->set_display_info(std::move(m));
201 m.name = std::move(v);
212 m.description = std::move(v);
257 const auto parsed = comms::Color::parse(v);
273 template <
typename,
typename>
292 requires std::derived_from<T, ICell>
307 requires std::derived_from<T, ICell>
309 j = v ? v->to_json() :
json_t();
322concept CellLike = std::derived_from<T, ICell> &&
requires {
323 { T::kind_id } -> std::convertible_to<std::string_view>;
325 T::from_json(std::declval<json_t const&>(), std::declval<ParcelRegistry const&>())
326 } -> std::convertible_to<cell_t>;
327 { T::descriptor() } -> std::convertible_to<cell_type_descriptor_t>;
342template <
typename Derived,
typename Storage>
344 using derived_t = Derived;
345 using storage_t = Storage;
360 template <
typename U>
361 requires std::constructible_from<Storage, U&&>
370 template <
typename U>
371 requires std::assignable_from<Storage&, U&&>
373 value = std::forward<U>(v);
374 return static_cast<Derived&
>(*this);
383 template <
typename... Args>
384 requires std::constructible_from<Derived, Args&&...>
385 static std::shared_ptr<Derived>
of(Args&&... args) {
386 return std::make_shared<Derived>(std::forward<Args>(args)...);
395 template <
typename... Args>
396 requires std::constructible_from<Derived, Args&&...>
397 static std::unique_ptr<Derived>
unique(Args&&... args) {
398 return std::make_unique<Derived>(std::forward<Args>(args)...);
407 Storage
const&
get()
const {
411 [[nodiscard]] std::string_view
kind()
const override {
412 return Derived::kind_id;
420 return std::make_shared<Derived>(
static_cast<Derived const&
>(*
this));
435 [[nodiscard]] std::partial_ordering
compare(
ICell const& other)
const override {
436 if (
const auto k_cmp = this->
kind() <=> other.
kind(); k_cmp != 0) {
439 const auto* o =
dynamic_cast<Derived const*
>(&other);
441 return std::partial_ordering::unordered;
449 if constexpr (!is_std_variant_v<Storage> && !disables_basecell_compare_v<Storage>) {
450 if constexpr (std::three_way_comparable<Storage>) {
451 return this->value <=> o->value;
452 }
else if constexpr (std::equality_comparable<Storage>) {
453 return this->
value == o->value ? std::partial_ordering::equivalent
454 : std::partial_ordering::unordered;
457 return std::partial_ordering::unordered;
471 if constexpr (
requires(Storage
const& s) {
json_t(s); }) {
476 throw std::runtime_error(
477 "BaseCell::to_json() requires Derived to override or Storage to be "
498 template <
typename Out>
525 template <
typename T>
527 if (!j.is_object()) {
529 std::string(expected_kind));
532 const auto it_kind = j.find(
KEY_KIND);
533 if (it_kind == j.end() || !it_kind->is_string()) {
535 std::string(expected_kind));
538 if (
const auto kind = it_kind->get<std::string_view>();
kind != expected_kind) {
540 std::string(expected_kind) +
"', got '" +
541 std::string(
kind) +
"'",
542 std::string(expected_kind));
546 if (it_value == j.end()) {
548 std::string(expected_kind));
551 return it_value->get<T>();
572 auto v = cell_from_json<Storage>(j, Derived::kind_id);
573 auto cell = std::make_shared<Derived>(std::move(v));
588 requires std::derived_from<C, ICell>
591 throw TypeException(
"cell_cast: null cell", std::string(C::kind_id));
593 auto out = std::dynamic_pointer_cast<C>(c);
596 "' but got '" + std::string(c->kind()) +
"'",
597 std::string(C::kind_id));
611 requires std::derived_from<C, ICell>
616 auto out = std::dynamic_pointer_cast<C>(c);
617 return out ? out : std::move(fallback);
620#if PARCEL_HAS_EXPECTED
629 requires std::derived_from<C, ICell>
630[[nodiscard]] std::expected<std::shared_ptr<C>, ParcelError> try_cell_cast(cell_t
const& c) {
634 auto out = std::dynamic_pointer_cast<C>(c);
637 std::string(
"expected '") +
638 std::string(C::kind_id) +
"' but got '" +
639 std::string(c->kind()) +
"'",
640 std::string(C::kind_id)));
655 requires std::derived_from<C, ICell>
657 return cell_cast<C>(c)->value;
671 requires std::derived_from<C, ICell>
672[[nodiscard]] std::optional<typename C::storage_t>
as(
cell_t const& c)
noexcept {
676 auto* typed =
dynamic_cast<C const*
>(c.get());
677 if (typed ==
nullptr) {
692 requires std::derived_from<C, ICell>
693[[nodiscard]]
typename C::storage_t
value_or(
cell_t const& c,
typename C::storage_t fallback) {
697 auto* typed =
dynamic_cast<C const*
>(c.get());
698 return typed ? typed->value : std::move(fallback);
705 return c ? c->to_json() :
json_t{};
712 return c ? c->to_string() : std::string{
"<null>"};
719 return c ? c->to_formatted_string() : std::string{
"<null>"};
735struct hash<parcel::ICell> {
736 [[nodiscard]]
size_t operator()(
parcel::ICell const& c)
const noexcept {
743struct hash<parcel::cell_t> {
744 [[nodiscard]]
size_t operator()(
parcel::cell_t const& c)
const noexcept {
745 return c ? std::hash<parcel::ICell>{}(*c) : std::size_t{0};
760 return std::hash<ICell>{}(c);
763[[nodiscard]]
inline std::size_t hash_cell(cell_t
const& c)
noexcept {
764 return std::hash<cell_t>{}(c);
std::string to_string(cell_t const &c)
Free to_string over cell_t; returns "<null>" for null handles.
Definition cell.h:711
std::shared_ptr< ICellTypeDescriptor > cell_type_descriptor_t
Shared handle to a runtime cell-type descriptor.
Definition cell.h:63
void to_json(json_t &j, T const &v)
ADL hook that lets nlohmann serialize any ICell-derived cell.
Definition cell.h:293
C::storage_t cell_cast_value(cell_t const &c)
Cast and unwrap to the inner storage value in one call.
Definition cell.h:656
std::shared_ptr< C > cell_cast(cell_t const &c)
Type-safe dynamic_cast from cell_t to a concrete cell type.
Definition cell.h:589
std::shared_ptr< ICell > cell_t
Shared handle to any ICell-derived value — the canonical cell pointer.
Definition cell.h:68
std::optional< typename C::storage_t > as(cell_t const &c) noexcept
std::optional view over a cell's inner storage.
Definition cell.h:672
std::shared_ptr< C > cell_cast_or(cell_t const &c, std::shared_ptr< C > fallback)
cell_cast that returns fallback on failure rather than throwing.
Definition cell.h:612
C::storage_t value_or(cell_t const &c, typename C::storage_t fallback)
Extract c's storage as C, falling back to fallback on failure.
Definition cell.h:693
std::size_t hash_cell(ICell const &c) noexcept
Hash a cell value compatibly with operator==.
Definition cell.h:759
std::string to_string_pretty(cell_t const &c)
Multi-line to_string over cell_t; returns "<null>" for null handles.
Definition cell.h:718
JSON shape was wrong (missing/non-string k, missing v, etc.).
Definition error.h:158
k field was present but did not match the expected kind.
Definition error.h:168
CRTP base for struct cells that are their own payload.
Definition struct.h:984
Typed value (cast, struct field, etc.) failed conversion.
Definition error.h:190
The shared vocabulary aliases re-exported from commons and the compile-time kind-id machinery.
comms::DisplayInfo DisplayInfo
Display info attached to a cell or descriptor — re-exported from comms::DisplayInfo.
Definition common.h:75
Concept naming the static interface every cell type must expose.
Definition cell.h:322
auto cell(T &&v)
Wrap a raw value into its default cell, returning a shared_ptr to the cell.
Definition defaults.h:192
ParcelError and the non-throwing surface that returns std::expected.
nlohmann::json json_t
Project-wide alias for nlohmann::json.
Definition json.h:19
CRTP base providing default to_json / clone / kind plumbing on top of a storage type.
Definition cell.h:343
std::optional< DisplayInfo > display_info_
Optional display info; omitted from JSON when empty.
Definition cell.h:507
static std::unique_ptr< Derived > unique(Args &&... args)
Construct a unique_ptr<Derived> forwarding the arguments.
Definition cell.h:397
static cell_t from_json_strict(json_t const &j)
Strict shorthand for the recurring cell_from_json + make_shared.
Definition cell.h:571
Derived & operator=(U &&v)
Assign to the storage from v.
Definition cell.h:372
cell_t clone() const override
Deep-copy this cell.
Definition cell.h:419
static std::shared_ptr< Derived > of(Args &&... args)
Construct a shared_ptr<Derived> forwarding the arguments.
Definition cell.h:385
std::partial_ordering compare(ICell const &other) const override
Default three-way comparison: kind first, then storage value.
Definition cell.h:435
Storage & get()
Mutable access to the held storage.
Definition cell.h:402
Storage const & get() const
Read-only access to the held storage.
Definition cell.h:407
std::string_view kind() const override
Wire-stable kind identifier for this cell.
Definition cell.h:411
static void absorb_display_info(json_t const &j, Out &out)
Read "d" (if present) from a JSON object and assign it onto a cell.
Definition cell.h:499
Storage value
Held value of the cell.
Definition cell.h:348
std::optional< DisplayInfo > const & overridden_display_info() const override
Read-only access to this cell's optional display info.
Definition cell.h:415
void set_display_info(std::optional< DisplayInfo > m) override
Replace this cell's display info in place.
Definition cell.h:509
json_t to_json() const override
Default JSON serialization for cells with JSON-convertible storage.
Definition cell.h:470
void inject_display_info(json_t &j) const
Copy this cell's display info (if any) into the JSON object under "d".
Definition cell.h:486
static T cell_from_json(const json_t &j, const std::string_view expected_kind)
Validate a wrapped {"k","v"} JSON object and extract its "v" as T.
Definition cell.h:526
Polymorphic root of every parcel cell.
Definition cell.h:84
virtual cell_t clone() const =0
Deep-copy this cell.
virtual std::string to_formatted_string() const
Render the cell as a multi-line, indented string.
Definition cell.h:122
virtual std::partial_ordering compare(ICell const &other) const =0
Three-way compare against another cell.
virtual void set_display_info(std::optional< DisplayInfo > m)=0
Replace this cell's display info in place.
virtual std::string to_string() const =0
Render the cell's value as a compact human-readable string.
static constexpr std::string_view KEY_DESCRIPTION
JSON key for the optional display info block ("d").
Definition cell.h:90
static constexpr std::string_view KEY_VALUE
JSON key for the value payload ("v").
Definition cell.h:88
friend bool operator==(ICell const &a, ICell const &b)
Equality through compare; ignores display info.
Definition cell.h:171
virtual json_t to_json() const =0
Serialize this cell to its canonical JSON representation.
cell_t with_name(std::string v) const
Return a deep copy with name set to v.
Definition cell.h:199
virtual std::string_view kind() const =0
Wire-stable kind identifier for this cell.
cell_t with_icon(std::string const &v) const
Return a deep copy with icon parsed from an Iconify set:name string (e.g.
Definition cell.h:234
virtual std::size_t hash_value() const noexcept
Equality-consistent hash that mirrors compare's display-info-insensitivity.
Definition cell.h:157
cell_t with_icon(comms::Icon icon) const
Return a deep copy with icon set to the typed icon.
Definition cell.h:221
cell_t with_display_info(DisplayInfo m) const
Return a deep copy with the entire display info block replaced.
Definition cell.h:188
cell_t with_description(std::string v) const
Return a deep copy with description set to v.
Definition cell.h:210
virtual std::optional< DisplayInfo > const & overridden_display_info() const =0
Read-only access to this cell's optional display info.
cell_t with_color(std::string const &v) const
Return a deep copy with color parsed from a color string (hex like "#ffcc00", a CSS-functional form,...
Definition cell.h:256
cell_t with_color(comms::Color color) const
Return a deep copy with color set to the typed color.
Definition cell.h:243
friend std::partial_ordering operator<=>(ICell const &a, ICell const &b)
Three-way comparison through compare; ignores display info.
Definition cell.h:176
static constexpr std::string_view KEY_KIND
JSON key for the kind id ("k").
Definition cell.h:86
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.
@ KindMismatch
JSON "k" did not match the expected kind.