19#include <initializer_list>
34template <
typename T,
typename A>
35struct detail::disables_basecell_compare<std::vector<T, A>> : std::true_type {
71 return descriptor::CellCategory::TypedList;
74 [[nodiscard]] std::vector<std::string_view>
sub_kinds()
const override {
84 j[
"element_kind"] = T::kind_id;
110 using element_type = T;
111 using element_storage_t =
typename T::storage_t;
113 using base_t::base_t;
114 using base_t::operator=;
121 :
base_t(std::vector<element_storage_t>(elems)) {}
129 template <std::ranges::input_range R>
130 requires std::convertible_to<std::ranges::range_value_t<R>, element_storage_t>
132 :
base_t(std::vector<element_storage_t>(std::ranges::begin(r), std::ranges::end(r))) {}
138 :
base_t(std::vector<element_storage_t>(sp.begin(), sp.end())) {}
146 [[nodiscard]] std::span<const element_storage_t>
as_span() const noexcept
147 requires(!std::same_as<element_storage_t,
bool>)
149 return std::span<const element_storage_t>(this->
value.data(), this->value.size());
153 [[nodiscard]] std::span<element_storage_t>
as_span() noexcept
154 requires(!std::same_as<element_storage_t,
bool>)
156 return std::span<element_storage_t>(this->
value.data(), this->value.size());
165 using vec_t = std::vector<element_storage_t>;
166 using value_type = vec_t::value_type;
167 using size_type = vec_t::size_type;
168 using iterator = vec_t::iterator;
169 using const_iterator = vec_t::const_iterator;
170 using reference = vec_t::reference;
171 using const_reference = vec_t::const_reference;
173 [[nodiscard]] size_type size() const noexcept {
174 return this->
value.size();
176 [[nodiscard]]
bool empty() const noexcept {
177 return this->
value.empty();
179 void reserve(size_type n) {
180 this->
value.reserve(n);
183 reference operator[](size_type i) {
184 return this->
value[i];
186 const_reference operator[](size_type i)
const {
187 return this->
value[i];
189 reference at(size_type i) {
190 return this->
value.at(i);
192 const_reference at(size_type i)
const {
193 return this->
value.at(i);
196 return this->
value.front();
198 [[nodiscard]] const_reference front()
const {
199 return this->
value.front();
202 return this->
value.back();
204 [[nodiscard]] const_reference back()
const {
205 return this->
value.back();
208 iterator begin() noexcept {
209 return this->
value.begin();
211 [[nodiscard]] const_iterator begin() const noexcept {
212 return this->
value.begin();
214 [[nodiscard]] const_iterator cbegin() const noexcept {
215 return this->
value.cbegin();
217 iterator end() noexcept {
218 return this->
value.end();
220 [[nodiscard]] const_iterator end() const noexcept {
221 return this->
value.end();
223 [[nodiscard]] const_iterator cend() const noexcept {
224 return this->
value.cend();
227 void push_back(element_storage_t
const& v) {
228 this->
value.push_back(v);
230 void push_back(element_storage_t&& v) {
231 this->
value.push_back(std::move(v));
233 template <
typename... Args>
234 reference emplace_back(Args&&... args) {
235 return this->
value.emplace_back(std::forward<Args>(args)...);
238 this->
value.pop_back();
240 void clear() noexcept {
243 iterator erase(const_iterator pos) {
244 return this->
value.erase(pos);
246 iterator erase(const_iterator first, const_iterator last) {
247 return this->
value.erase(first, last);
249 iterator insert(const_iterator pos, element_storage_t
const& v) {
250 return this->
value.insert(pos, v);
252 iterator insert(const_iterator pos, element_storage_t&& v) {
253 return this->
value.insert(pos, std::move(v));
274 std::string out =
"[";
276 for (
auto const& el : this->
value) {
281 out += wrapper.to_string();
289 json_t arr = json_t::array();
290 for (
auto const& el : this->
value) {
309 [[nodiscard]] std::partial_ordering
compare(
ICell const& other)
const override {
310 if (
const auto k_cmp = this->
kind() <=> other.
kind(); k_cmp != 0) {
315 return std::partial_ordering::unordered;
317 const auto& a = this->
value;
318 const auto& b = o->
value;
319 const std::size_t n = std::min(a.size(), b.size());
320 for (std::size_t i = 0; i < n; ++i) {
323 if (
const auto c = wa.compare(wb); c != 0) {
327 return a.size() <=> b.size();
339 if (!j.is_object()) {
345 if (it_k == j.end() || !it_k->is_string()) {
350 if (it_k->get<std::string_view>() !=
kind_id) {
357 if (it_v == j.end() || !it_v->is_array()) {
362 std::vector<element_storage_t> elems;
363 elems.reserve(it_v->size());
364 for (
auto const& raw : *it_v) {
366 cell_t v = T::from_json(wrapped, reg);
367 auto* typed =
dynamic_cast<T*
>(v.get());
368 if (typed ==
nullptr) {
370 std::string(
"TypedListCell: element from_json did not return ") +
371 std::string(T::kind_id),
374 elems.push_back(std::move(typed->value));
376 auto cell = std::make_shared<TypedListCell>(std::move(elems));
386 static const auto d = std::make_shared<TypedListCellTypeDescriptor<T>>(
DisplayInfo{
388 .description = std::string(
"Homogeneous list of ") + std::string(T::kind_id),
412 using base_t::base_t;
413 using base_t::operator=;
419 ListCell(
const std::initializer_list<cell_t> elems) :
base_t(std::vector(elems)) {}
423 using vec_t = std::vector<cell_t>;
424 using value_type = vec_t::value_type;
425 using size_type = vec_t::size_type;
426 using iterator = vec_t::iterator;
427 using const_iterator = vec_t::const_iterator;
428 using reference = vec_t::reference;
429 using const_reference = vec_t::const_reference;
431 [[nodiscard]] size_type size() const noexcept {
432 return this->
value.size();
434 [[nodiscard]]
bool empty() const noexcept {
435 return this->
value.empty();
437 void reserve(
const size_type n) {
438 this->
value.reserve(n);
441 reference operator[](
const size_type i) {
442 return this->
value[i];
444 const_reference operator[](
const size_type i)
const {
445 return this->
value[i];
447 reference at(
const size_type i) {
448 return this->
value.at(i);
450 [[nodiscard]] const_reference at(
const size_type i)
const {
451 return this->
value.at(i);
454 return this->
value.front();
456 [[nodiscard]] const_reference front()
const {
457 return this->
value.front();
460 return this->
value.back();
462 [[nodiscard]] const_reference back()
const {
463 return this->
value.back();
466 iterator begin() noexcept {
467 return this->
value.begin();
469 [[nodiscard]] const_iterator begin() const noexcept {
470 return this->
value.begin();
472 [[nodiscard]] const_iterator cbegin() const noexcept {
473 return this->
value.cbegin();
475 iterator end() noexcept {
476 return this->
value.end();
478 [[nodiscard]] const_iterator end() const noexcept {
479 return this->
value.end();
481 [[nodiscard]] const_iterator cend() const noexcept {
482 return this->
value.cend();
485 void push_back(cell_t
const& v) {
486 this->
value.push_back(v);
488 void push_back(cell_t&& v) {
489 this->
value.push_back(std::move(v));
491 template <
typename... Args>
492 reference emplace_back(Args&&... args) {
493 return this->
value.emplace_back(std::forward<Args>(args)...);
496 this->
value.pop_back();
498 void clear() noexcept {
501 iterator erase(
const const_iterator pos) {
502 return this->
value.erase(pos);
504 iterator erase(
const const_iterator first,
const const_iterator last) {
505 return this->
value.erase(first, last);
507 iterator insert(
const const_iterator pos, cell_t
const& v) {
508 return this->
value.insert(pos, v);
510 iterator insert(
const const_iterator pos, cell_t&& v) {
511 return this->
value.insert(pos, std::move(v));
516 static constexpr std::string_view
kind_id =
"l";
523 std::string out =
"[";
525 for (
auto const& el : this->
value) {
529 out += el ? el->to_string() :
"<null>";
537 json_t arr = json_t::array();
538 for (
auto const& el : this->
value) {
539 arr.push_back(el ? el->to_json() :
json_t());
550 std::vector<cell_t> copied;
551 copied.reserve(this->
value.size());
552 for (
auto const& el : this->
value) {
553 copied.push_back(el ? el->clone() :
nullptr);
555 auto out = std::make_shared<ListCell>(std::move(copied));
560 [[nodiscard]] std::size_t
hash_value() const noexcept
override {
561 std::size_t h = std::hash<std::string_view>{}(
kind());
562 for (
auto const& el : this->
value) {
563 const std::size_t hv = el ? el->hash_value() : std::size_t{0};
564 h ^= hv + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2);
575 [[nodiscard]] std::partial_ordering
compare(
ICell const& other)
const override {
576 if (
const auto k_cmp = this->
kind() <=> other.
kind(); k_cmp != 0) {
579 const auto* o =
dynamic_cast<ListCell const*
>(&other);
581 return std::partial_ordering::unordered;
583 const auto& a = this->
value;
584 const auto& b = o->
value;
585 const std::size_t n = std::min(a.size(), b.size());
586 for (std::size_t i = 0; i < n; ++i) {
587 if (!a[i] && !b[i]) {
591 return std::partial_ordering::less;
594 return std::partial_ordering::greater;
596 if (
const auto c = a[i]->
compare(*b[i]); c != 0) {
600 return a.size() <=> b.size();
611 if (!j.is_object()) {
616 if (it_k == j.end() || !it_k->is_string()) {
620 if (it_k->get<std::string_view>() !=
kind_id) {
626 if (it_v == j.end() || !it_v->is_array()) {
631 std::vector<cell_t> elems;
632 elems.reserve(it_v->size());
633 for (
auto const& raw : *it_v) {
638 auto cell = std::make_shared<ListCell>(std::move(elems));
664 return descriptor::CellCategory::List;
673 static const auto d = std::make_shared<ListCellTypeDescriptor>(
674 DisplayInfo{.name =
"List", .description =
"Heterogeneous list of cells"});
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
CRTP base that fills in the boilerplate of every cell-type descriptor.
Definition descriptor.h:165
json_t base_to_json() const
Common JSON skeleton (kind, display_info, category) reused by overrides.
Definition descriptor.h:202
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
Descriptor for the heterogeneous ListCell.
Definition list.h:656
descriptor::CellCategory category() const override
Coarse classification (primitive, list, struct, …).
Definition list.h:663
cell_t cell_from_json(const json_t &j, const ParcelRegistry ®) const override
Construct a cell from JSON, dispatching to the concrete from_json.
Definition list.h:667
Heterogeneous list of cell_t — wire kind "l".
Definition list.h:408
json_t to_json() const override
Default JSON serialization for cells with JSON-convertible storage.
Definition list.h:536
cell_t clone() const override
Deep-copy this cell.
Definition list.h:549
static constexpr std::string_view kind_id
Wire kind id ("l").
Definition list.h:516
std::size_t hash_value() const noexcept override
Equality-consistent hash that mirrors compare's display-info-insensitivity.
Definition list.h:560
ListCell(const std::initializer_list< cell_t > elems)
Construct from a brace-enclosed list of cells.
Definition list.h:419
static cell_type_descriptor_t descriptor()
Cached descriptor for ListCell.
Definition list.h:672
static cell_t from_json(json_t const &j, ParcelRegistry const ®)
Deserialize a ListCell from JSON.
Definition list.h:610
std::partial_ordering compare(ICell const &other) const override
Lexicographic three-way comparison over elements; ignores display info.
Definition list.h:575
std::string to_string() const override
Render the list as [a, b, c]; null elements appear as <null>.
Definition list.h:522
Runtime catalog of cell-type descriptors, keyed by wire kind id.
Definition registry.h:115
cell_t cell_from_json(json_t const &j) const
Deserialize any registered cell from JSON, dispatching by "k".
Definition registry.h:266
Typed value (cast, struct field, etc.) failed conversion.
Definition error.h:190
Descriptor for TypedListCell<T>.
Definition list.h:54
cell_t cell_from_json(json_t const &j, ParcelRegistry const ®) const override
Construct a cell from JSON, dispatching to the concrete from_json.
Definition list.h:78
TypedListCellTypeDescriptor(DisplayInfo info)
Construct with the given display info.
Definition list.h:63
std::vector< std::string_view > sub_kinds() const override
Sub-kind ids reachable from this descriptor.
Definition list.h:74
json_t to_json() const override
Serialize the descriptor itself (kind + display info + category + extras).
Definition list.h:82
descriptor::CellCategory category() const override
Coarse classification (primitive, list, struct, …).
Definition list.h:70
std::string_view element_kind() const
Wire kind id of the list's element type.
Definition list.h:66
Homogeneous list of element cells of type T.
Definition list.h:106
static constexpr std::string_view kind_id
Wire kind id of this typed list ("l:" + T::kind_id).
Definition list.h:267
std::span< element_storage_t > as_span() noexcept
Mutable span view over the list's elements.
Definition list.h:153
std::partial_ordering compare(ICell const &other) const override
Element-wise three-way comparison; ignores display info.
Definition list.h:309
static cell_t from_json(json_t const &j, ParcelRegistry const ®)
Deserialize a TypedListCell<T> from JSON.
Definition list.h:338
TypedListCell(std::from_range_t, R &&r)
Construct from any input range whose elements convert to element_storage_t.
Definition list.h:131
TypedListCell(std::span< const element_storage_t > sp)
Construct by copying the contents of sp into the list.
Definition list.h:137
std::string to_string() const override
Render the list as [a, b, c] using each element's to_string.
Definition list.h:273
static cell_type_descriptor_t descriptor()
Cached descriptor for this typed list.
Definition list.h:385
json_t to_json() const override
Default JSON serialization for cells with JSON-convertible storage.
Definition list.h:288
std::span< const element_storage_t > as_span() const noexcept
Read-only span view over the list's elements.
Definition list.h:146
TypedListCell(std::initializer_list< element_storage_t > elems)
Construct from a brace-enclosed list of element values.
Definition list.h:120
comms::DisplayInfo DisplayInfo
Display info attached to a cell or descriptor — re-exported from comms::DisplayInfo.
Definition common.h:75
constexpr std::string_view prefixed_id_v
Convenience alias yielding the joined std::string_view.
Definition common.h:175
auto cell(T &&v)
Wrap a raw value into its default cell, returning a shared_ptr to the cell.
Definition defaults.h:192
Runtime cell-type descriptors and the schema-graph mix-ins (IHasFields, ISubTypes).
CellCategory
Coarse runtime classification of a cell type.
Definition descriptor.h:35
nlohmann::json json_t
Project-wide alias for nlohmann::json.
Definition json.h:19
ParcelRegistry, Definition, and BuiltinsOptions for polymorphic dispatch.
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
std::string_view kind() const override
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
std::vector< T::storage_t > value
Held value of the cell.
Definition cell.h:348
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
Polymorphic root of every parcel cell.
Definition cell.h:84
static constexpr std::string_view KEY_VALUE
JSON key for the value payload ("v").
Definition cell.h:88
virtual std::string_view kind() const =0
Wire-stable kind identifier for this cell.
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