48class ConversionStack
final {
51 explicit ConversionStack(ValueFrom value) : stack_() { stack_.emplace_back(std::move(value)); }
53 ConversionStack(ConversionStack&&) =
delete;
54 ConversionStack& operator=(ConversionStack&&) =
delete;
57 bool IsParsed()
const {
return stack_.front().is_parsed; }
62 return std::move(stack_.front().to).value();
67 if (stack_.front().is_parsed) {
68 return stack_.front().from;
69 }
else if (!stack_.back().is_parsed) {
70 return stack_.back().from;
72 return stack_[stack_.size() - 2].from;
81 UASSERT(!stack_.front().is_parsed && !stack_.back().is_parsed);
82 SetCurrent(stack_.back().from.
template As<T>());
92 stack_.back().to.emplace(std::forward<T>(value));
93 stack_.back().is_parsed =
true;
98 if (!stack_.back().is_parsed) {
99 if (!stack_.back().to) {
100 if (stack_.back().from.IsObject()) {
102 }
else if (stack_.back().from.IsArray()) {
108 if (stack_.back().current_parsing_elem) {
109 ++*stack_.back().current_parsing_elem;
111 stack_.back().current_parsing_elem = stack_.back().from.begin();
113 if (stack_.back().current_parsing_elem.value() == stack_.back().from.end()) {
114 stack_.back().is_parsed =
true;
117 auto new_from = *stack_.back().current_parsing_elem.value();
118 stack_.emplace_back(std::move(new_from));
122 auto& current_docs = stack_[stack_.size() - 2];
123 if (current_docs.from.IsObject()) {
124 current_docs.to.value()[current_docs.current_parsing_elem->GetName()] = std::move(stack_.back().to.value());
125 }
else if (current_docs.from.IsArray()) {
126 current_docs.to->PushBack(std::move(stack_.back().to.value()));
134 struct StackFrame
final {
135 explicit StackFrame(ValueFrom&& from) : from(std::move(from)) {}
136 explicit StackFrame(
const ValueFrom& from) : from(from) {}
138 const ValueFrom from;
139 std::optional<ValueToBuilder> to{};
140 std::optional<
typename ValueFrom::const_iterator> current_parsing_elem{};
141 bool is_parsed{
false};
147 boost::container::deque<StackFrame,
void, boost::container::deque_options<boost::container::block_size<16>>::type>
158 if (value.IsMissing()) {
159 throw typename std::decay_t<ValueFrom>::Exception(fmt::format(
160 "Failed to convert value at '{}' from {} to {}: missing value",
162 compiler::GetTypeName<std::decay_t<ValueFrom>>(),
166 formats::
common::ConversionStack<std::decay_t<ValueFrom>,
typename ValueTo::Builder> conversion_stack(
167 std::forward<ValueFrom>(value)
169 while (!conversion_stack.IsParsed()) {
170 const auto& from = conversion_stack.GetNextFrom();
172 conversion_stack.
template CastCurrentPrimitive<
bool>();
173 }
else if (from.IsInt()) {
174 conversion_stack.
template CastCurrentPrimitive<
int>();
175 }
else if (from.IsInt64()) {
176 conversion_stack.
template CastCurrentPrimitive<std::int64_t>();
177 }
else if (from.IsUInt64()) {
178 conversion_stack.
template CastCurrentPrimitive<std::uint64_t>();
179 }
else if (from.IsDouble()) {
180 conversion_stack.
template CastCurrentPrimitive<
double>();
181 }
else if (from.IsString()) {
182 conversion_stack.
template CastCurrentPrimitive<std::string>();
183 }
else if (from.IsNull()) {
184 conversion_stack.SetCurrent(
common::
Type::kNull);
185 }
else if (from.IsArray() || from.IsObject()) {
186 conversion_stack.EnterItems();
188 throw typename std::decay_t<ValueFrom>::Exception(fmt::format(
189 "Failed to convert value at '{}' from {} to {}: unknown node type",
191 compiler::GetTypeName<std::decay_t<ValueFrom>>(),
196 return std::move(conversion_stack).GetParsed().ExtractValue();