Skip to content

Commit cef601b

Browse files
committed
Fix capnproto add_value_to_map overwriting all entries at index 0
add_value_to_map constructed a fresh OutputArrayType each call without using _parent->ix_++, so ix_ always defaulted to 0 and every map entry overwrote slot 0 in the Cap'n Proto entries list. Only the last entry survived serialization; on read-back the remaining default entries (with empty-string keys) triggered stoull errors. Fix by using designated initializers with .ix_ = _parent->ix_++, matching all other add_*_to_map methods in Writer.cpp. Also wrap the key _name in std::string() so add_value_to_object deduces T as std::string rather than std::string_view, which has no handling branch. Add test_map_value_types to exercise maps with primitive value types (std::map<std::string, std::string>) through add_value_to_map. Made-with: Cursor
1 parent 9d9f840 commit cef601b

2 files changed

Lines changed: 29 additions & 3 deletions

File tree

include/rfl/capnproto/Writer.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,11 @@ class RFL_API Writer {
186186
template <class T>
187187
OutputVarType add_value_to_map(const std::string_view& _name, const T& _var,
188188
OutputMapType* _parent) const {
189-
auto entries =
190-
OutputArrayType{_parent->val_.get("entries").as<capnp::DynamicList>()};
189+
auto entries = OutputArrayType{
190+
.val_ = _parent->val_.get("entries").as<capnp::DynamicList>(),
191+
.ix_ = _parent->ix_++};
191192
auto new_entry = add_object_to_array(2, &entries);
192-
add_value_to_object("key", _name, &new_entry);
193+
add_value_to_object("key", std::string(_name), &new_entry);
193194
return add_value_to_object("value", _var, &new_entry);
194195
}
195196

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <map>
2+
#include <rfl.hpp>
3+
#include <string>
4+
5+
#include "write_and_read.hpp"
6+
7+
namespace test_map_value_types {
8+
9+
struct PersonWithStringMap {
10+
rfl::Rename<"firstName", std::string> first_name;
11+
std::map<std::string, std::string> nicknames;
12+
};
13+
14+
TEST(capnproto, test_map_with_string_values) {
15+
auto nicknames = std::map<std::string, std::string>();
16+
nicknames["Bart"] = "El Barto";
17+
nicknames["Lisa"] = "Lis";
18+
nicknames["Maggie"] = "Mags";
19+
20+
const auto homer = PersonWithStringMap{.first_name = "Homer",
21+
.nicknames = std::move(nicknames)};
22+
23+
write_and_read(homer);
24+
}
25+
} // namespace test_map_value_types

0 commit comments

Comments
 (0)