41 static constexpr struct DisableResize {} no_resize{};
43 virtual ~Field() =
default;
46 Field(Field&&) =
default;
47 Field(
const Field&) =
delete;
48 Field& operator=(Field&&) =
default;
49 Field& operator=(
const Field&) =
delete;
68 auto result = _serialized();
70 throw SizeError(
"Serialized size does not match expected number of bytes");
75 template<
typename Visitor>
77 return precision().visit([&] <
typename T> (
const Precision<T>&) {
79 return visitor(serialization.template as_span_of<T>());
86 template<std::ranges::range R>
requires(Concepts::Scalar<MDRangeValueType<R>>)
88 if constexpr (std::same_as<std::remove_cvref_t<R>, std::string>) {
89 decltype(
auto) result = _export_to<true>(std::forward<R>(output_range));
90 if (!result.empty() && result.back() ==
'\0')
92 if (result.find(
'\0') != std::string::npos)
93 throw ValueError(
"Field holds multiple strings, export it into a MultiString instead");
94 return std::forward<decltype(result)>(result);
96 return _export_to<true>(std::forward<R>(output_range));
101 template<std::ranges::range R>
requires(Concepts::Scalar<MDRangeValueType<R>>)
102 decltype(
auto)
export_to(R&& output_range, DisableResize)
const {
103 return _export_to<false>(std::forward<R>(output_range));
107 template<Concepts::Scalar S>
109 const auto my_layout =
layout();
111 if (my_layout.number_of_entries() != 1)
112 throw TypeError(
"Field cannot be exported into a scalar");
114 out =
static_cast<S
>(data[0]);
119 template<Concepts::Scalar S>
127 template<Concepts::ResizableMDRange R>
128 requires(Concepts::StaticallySizedMDRange<std::ranges::range_value_t<R>> or
129 Concepts::Scalar<std::ranges::range_value_t<R>>)
135 DynamicPrecision _prec;
137 virtual MDLayout _layout()
const = 0;
138 virtual DynamicPrecision _precision()
const = 0;
139 virtual Serialization _serialized()
const = 0;
142 template<
bool enable_resize, std::ranges::range R>
requires(Concepts::Scalar<MDRangeValueType<R>>)
143 decltype(
auto) _export_to(R&& output_range)
const {
144 const auto my_layout =
layout();
146 if constexpr (Concepts::ResizableMDRange<R> && enable_resize) {
147 const auto num_scalars = my_layout.number_of_entries();
148 const auto num_sub_scalars = get_md_layout<std::ranges::range_value_t<R>>().number_of_entries();
149 if (num_scalars%num_sub_scalars != 0)
151 "Cannot export the field into the given range type. "
152 "Number of entries in the field is not divisible by the "
153 "number of entries in the value_type of the provided range."
157 num_scalars/num_sub_scalars,
158 DefaultValue<std::ranges::range_value_t<R>>::get()
161 const auto output_range_layout = get_md_layout(output_range);
162 if (output_range_layout.number_of_entries() < my_layout.number_of_entries())
164 std::string{
"Cannot fill the given range. Too few entries. "} +
165 "Number of field entries: '" + std::to_string(my_layout.number_of_entries()) +
"'; " +
166 "Number of range entries: '" + std::to_string(output_range_layout.number_of_entries()) +
"'"
170 std::size_t offset = 0;
172 _export_to(output_range, data, offset);
175 return std::forward<R>(output_range);
178 template<std::ranges::range R, Concepts::Scalar T>
179 void _export_to(R& range,
180 std::span<const T> data,
181 std::size_t& offset)
const {
182 if constexpr (mdrange_dimension<R> > 1) {
183 std::ranges::for_each(range, [&] (std::ranges::range
auto& sub_range) {
184 _export_to(sub_range, data, offset);
189 auto converted_data = data | std::views::drop(offset)
190 | std::views::take(std::min(Ranges::size(range), data.size() - offset))
191 | std::views::transform([] (
const T& value) {
192 return static_cast<std::ranges::range_value_t<R>
>(value);
195 std::ranges::begin(converted_data),
196 std::ranges::end(converted_data),
197 std::ranges::begin(range)
199 offset += Ranges::size(converted_data);