MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
CompositeAccess.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Composite.hpp"
5
6namespace MayaFlux::Kakshya {
7
8/**
9 * @struct CompositeProjection
10 * @brief Owning homogeneous NDData projection of one Composite field.
11 *
12 * Presence contains one uint8_t per element: 1 for present, 0 for absent.
13 * Values for absent elements are zero-filled and must be interpreted using
14 * the presence variant. The dimension describes the projected field as a
15 * one-dimensional TENSOR_ND value sequence.
16 *
17 * Usage:
18 * @code
19 * auto projection = items.to_nddata<double>("score");
20 * const auto& scores = std::get<std::vector<double>>(projection->values);
21 * const auto& present = std::get<std::vector<uint8_t>>(projection->presence);
22 * @endcode
23 */
25 DataVariant values; ///< Homogeneous values of the requested field type.
26 DataVariant presence { std::vector<uint8_t> {} }; ///< One byte per value.
27 std::vector<DataDimension> dimensions; ///< One CUSTOM axis named for the field.
28 DataModality modality { DataModality::TENSOR_ND }; ///< Projection modality.
29};
30
31/**
32 * @brief Validate and borrow packed Composite-compatible NDData.
33 * @param elements DataVariant holding vector<uint8_t> packed elements.
34 * @param text DataVariant holding vector<uint8_t> UTF-8 bytes.
35 * @param blob DataVariant holding vector<uint8_t> binary bytes.
36 * @param layout Finalized layout for the packed elements.
37 * @return Access view, or std::nullopt for incompatible storage or layout.
38 * @note This validates storage types, stride, and field extents. Individual
39 * text and binary offset bounds are checked when fields are read.
40 */
41[[nodiscard]] MAYAFLUX_API std::optional<CompositeAccess> as_composite_access(
42 const DataVariant& elements, const DataVariant& text, const DataVariant& blob,
43 const CompositeLayout& layout);
44
45/**
46 * @class CompositeAccess
47 * @brief Validated, non-owning access to packed Composite NDData storage.
48 *
49 * The element, text, and binary stores remain DataVariant instances holding
50 * vector<uint8_t>. The layout interprets field offsets within each packed
51 * element. No byte or field conversion occurs when creating this view.
52 *
53 * Usage:
54 * @code
55 * auto access = items.access();
56 * auto first = access->at(0);
57 * auto bytes = access->element_bytes();
58 * auto dimensions = access->byte_dimensions();
59 * @endcode
60 *
61 * Access to externally owned packed variants:
62 * @code
63 * auto access = as_composite_access(elements, text, blob, layout);
64 * @endcode
65 *
66 * @note The backing DataVariant objects and layout must outlive this view.
67 * Do not replace their variant alternatives or mutate their storage while
68 * borrowed views are in use.
69 */
70class MAYAFLUX_API CompositeAccess {
71public:
72 /** @brief Layout used to interpret packed elements. */
73 [[nodiscard]] const CompositeLayout& layout() const noexcept { return *m_layout; }
74 /** @brief Number of packed elements in the current element store. */
75 [[nodiscard]] size_t size() const noexcept
76 {
77 return std::get<std::vector<uint8_t>>(*m_elements).size() / m_layout->stride_bytes();
78 }
79 /**
80 * @brief Borrow an element by index.
81 * @param index Zero-based element index.
82 * @return Element view, or std::nullopt if out of range.
83 */
84 [[nodiscard]] std::optional<Composite> at(size_t index) const noexcept;
85 /** @brief Borrow all packed element bytes without conversion. */
86 [[nodiscard]] std::span<const uint8_t> element_bytes() const noexcept;
87 /** @brief Borrow the packed-element DataVariant without conversion. */
88 [[nodiscard]] const DataVariant& element_data() const noexcept { return *m_elements; }
89 /** @brief Borrow the UTF-8 byte DataVariant without conversion. */
90 [[nodiscard]] const DataVariant& text_data() const noexcept { return *m_text; }
91 /** @brief Borrow the binary byte DataVariant without conversion. */
92 [[nodiscard]] const DataVariant& blob_data() const noexcept { return *m_blob; }
93 /**
94 * @brief Describe packed bytes as [elements, bytes-per-element].
95 * @return Two CUSTOM DataDimensions for the uint8_t element store.
96 * @note These dimensions do not replace the field schema in layout().
97 */
98 [[nodiscard]] std::vector<DataDimension> byte_dimensions() const;
99 /**
100 * @brief Borrow @p count consecutive elements starting at @p start.
101 * @param start First element index.
102 * @param count Number of elements to select.
103 * @return Slice, including an empty slice, or std::nullopt if out of range.
104 */
105 [[nodiscard]] std::optional<CompositeSlice> slice(size_t start, size_t count) const noexcept;
106 /**
107 * @brief Borrow the elements selected by a one-dimensional Region.
108 * @param region Inclusive element bounds and optional Region attributes.
109 * @return Slice retaining the Region, or std::nullopt for invalid bounds.
110 */
111 [[nodiscard]] std::optional<CompositeSlice> slice(const Region& region) const;
112
113private:
114 friend MAYAFLUX_API std::optional<CompositeAccess> as_composite_access(
115 const DataVariant&, const DataVariant&, const DataVariant&, const CompositeLayout&);
116
117 CompositeAccess(const DataVariant& elements, const DataVariant& text, const DataVariant& blob,
118 const CompositeLayout& layout) noexcept
119 : m_elements(&elements)
120 , m_text(&text)
121 , m_blob(&blob)
122 , m_layout(&layout)
123 {
124 }
125
130};
131
132/**
133 * @class CompositeSlice
134 * @brief Borrowed consecutive elements, optionally selected by a Region.
135 *
136 * A slice retains the original Region and its attributes when created from
137 * one. Offset/count slices have no Region. Field access still uses the
138 * original CompositeLayout and byte stores, so payload offsets do not need
139 * to be rewritten. The slice does not own the stores.
140 *
141 * Usage:
142 * @code
143 * auto selection = items.slice(2, 4);
144 * auto first = selection->at(0);
145 * auto packed = selection->element_bytes();
146 * auto scores = selection->to_nddata<double>("score");
147 * @endcode
148 *
149 * Region usage:
150 * @code
151 * Region region(std::vector<uint64_t> { 2 }, std::vector<uint64_t> { 5 });
152 * auto selection = items.slice(region);
153 * const Region* source = selection->region();
154 * @endcode
155 *
156 * @note element_bytes() is a zero-copy view. It is not an independent
157 * CompositeArray: text offsets still refer to the original text_data().
158 */
159class MAYAFLUX_API CompositeSlice {
160public:
161 /** @brief Number of selected elements. */
162 [[nodiscard]] size_t size() const noexcept { return m_count; }
163 /** @brief First element index in the source access view. */
164 [[nodiscard]] size_t start() const noexcept { return m_start; }
165 /** @brief Shared layout of all selected elements. */
166 [[nodiscard]] const CompositeLayout& layout() const noexcept { return m_access.layout(); }
167 /**
168 * @brief Borrow a selected element by slice-relative index.
169 * @param index Zero-based index within the slice.
170 * @return Element view, or std::nullopt if out of range.
171 */
172 [[nodiscard]] std::optional<Composite> at(size_t index) const noexcept;
173 /** @brief Borrow the selected contiguous packed bytes. */
174 [[nodiscard]] std::span<const uint8_t> element_bytes() const noexcept;
175 /** @brief Borrow the full text store used by selected elements. */
176 [[nodiscard]] const DataVariant& text_data() const noexcept { return m_access.text_data(); }
177 /** @brief Borrow the full binary store used by selected elements. */
178 [[nodiscard]] const DataVariant& blob_data() const noexcept { return m_access.blob_data(); }
179 /** @brief Original Region when selected by Region; otherwise nullptr. */
180 [[nodiscard]] const Region* region() const noexcept
181 {
182 return m_region ? &*m_region : nullptr;
183 }
184
185 /**
186 * @brief Materialize one exact-type arithmetic field as homogeneous NDData.
187 * @tparam T Declared field type and supported DataVariant element type.
188 * @param field_name Field to project.
189 * @return Owning values, presence mask, and dimension metadata; or
190 * std::nullopt if the field is absent from the layout or has another type.
191 * Missing values are zero-filled and marked absent in the mask.
192 */
193 template <typename T>
194 requires(ArithmeticData<T> && DataVariantElement<T>)
195 [[nodiscard]] std::optional<CompositeProjection> to_nddata(std::string_view field_name) const;
196
197private:
198 friend class CompositeAccess;
199
200 CompositeSlice(CompositeAccess access, size_t start, size_t count,
201 std::optional<Region> region = std::nullopt)
202 : m_access(access)
203 , m_start(start)
204 , m_count(count)
205 , m_region(std::move(region))
206 {
207 }
208
210 size_t m_start;
211 size_t m_count;
212 std::optional<Region> m_region;
213};
214
215template <typename T>
216 requires(ArithmeticData<T> && DataVariantElement<T>)
217std::optional<CompositeProjection> CompositeSlice::to_nddata(std::string_view field_name) const
218{
219 const auto field_index = layout().find_field(field_name);
220 if (!field_index || layout().fields()[*field_index].type != std::type_index(typeid(T)))
221 return std::nullopt;
222
223 std::vector<T> values(m_count);
224 std::vector<uint8_t> presence(m_count, 0);
225 for (size_t i = 0; i < m_count; ++i) {
226 const auto element = at(i);
227 if (!element)
228 return std::nullopt;
229 if (auto value = element->get<T>(field_name)) {
230 values[i] = *value;
231 presence[i] = 1;
232 }
233 }
234
235 CompositeProjection result;
236 result.values = std::move(values);
237 result.presence = std::move(presence);
238 result.dimensions.emplace_back(std::string(field_name), m_count, 1, DataDimension::Role::CUSTOM);
239 return result;
240}
241
242template <typename T>
243 requires(ArithmeticData<T> && DataVariantElement<T>)
244std::optional<CompositeProjection> CompositeArray::to_nddata(std::string_view field_name) const
245{
246 const auto selection = slice(0, size());
247 return selection ? selection->to_nddata<T>(field_name) : std::nullopt;
248}
249
250}
bool size
glm::vec3 value
std::vector< std::byte > values
Definition VDBWriter.cpp:26
vk::PhysicalDeviceType type
Definition VKDevice.cpp:126
uint32_t index
Definition VKDevice.cpp:122
size_t count
size_t element_bytes
CompositeAccess(const DataVariant &elements, const DataVariant &text, const DataVariant &blob, const CompositeLayout &layout) noexcept
const DataVariant & blob_data() const noexcept
Borrow the binary byte DataVariant without conversion.
const CompositeLayout & layout() const noexcept
Layout used to interpret packed elements.
size_t size() const noexcept
Number of packed elements in the current element store.
const DataVariant & text_data() const noexcept
Borrow the UTF-8 byte DataVariant without conversion.
Validated, non-owning access to packed Composite NDData storage.
std::optional< CompositeProjection > to_nddata(std::string_view field_name) const
Materialize one exact-type numeric field as homogeneous NDData.
Shared field description and byte layout for a CompositeArray.
Definition Composite.hpp:52
const DataVariant & blob_data() const noexcept
Borrow the full binary store used by selected elements.
size_t size() const noexcept
Number of selected elements.
CompositeSlice(CompositeAccess access, size_t start, size_t count, std::optional< Region > region=std::nullopt)
const CompositeLayout & layout() const noexcept
Shared layout of all selected elements.
const Region * region() const noexcept
Original Region when selected by Region; otherwise nullptr.
size_t start() const noexcept
First element index in the source access view.
std::optional< CompositeProjection > to_nddata(std::string_view field_name) const
Materialize one exact-type arithmetic field as homogeneous NDData.
Borrowed consecutive elements, optionally selected by a Region.
Concept to constrain types to valid DataVariant elements.
Definition NDData.hpp:127
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
Definition NDData.hpp:70
DataModality
Data modality types for cross-modal analysis.
Definition NDData.hpp:132
@ TENSOR_ND
N-dimensional tensor.
std::optional< CompositeAccess > as_composite_access(const DataVariant &elements, const DataVariant &text, const DataVariant &blob, const CompositeLayout &layout)
Validate and borrow packed Composite-compatible NDData.
DataVariant values
Homogeneous values of the requested field type.
DataVariant presence
One byte per value.
DataModality modality
Projection modality.
std::vector< DataDimension > dimensions
One CUSTOM axis named for the field.
Owning homogeneous NDData projection of one Composite field.
@ CUSTOM
User-defined or application-specific.
Represents a point or span in N-dimensional space.
Definition Region.hpp:73