Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/v1' into v1-js-impl…
Browse files Browse the repository at this point in the history
…ement
  • Loading branch information
meded7 committed Apr 17, 2024
2 parents 7fbfae1 + b76b2f4 commit 8545985
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 10 deletions.
30 changes: 20 additions & 10 deletions messgen/cpp_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def _indent(c):
elif type(c) is list:
r = []
for i in c:
r.append(spaces + i)
r.append(spaces + i if i else "")
return r
else:
raise RuntimeError("Unsupported type for indent: %s" % type(c))
Expand Down Expand Up @@ -228,10 +228,12 @@ def _generate_type_struct(self, type_name):

# IS_FLAT flag
is_flat_str = "false"
if (len(groups) == 1 and groups[0].size is not None):
code.append(_indent("static constexpr size_t FLAT_SIZE = %d;" % groups[0].size))
is_empty = len(groups) == 0
if is_empty or (len(groups) == 1 and groups[0].size is not None):
code.append(_indent("static constexpr size_t FLAT_SIZE = %d;" % (0 if is_empty else groups[0].size)))
is_flat_str = "true"
code.append(_indent("static constexpr bool IS_FLAT = %s;" % is_flat_str))
code.append(_indent("static constexpr const char* NAME = \"%s\";" % type_name))
code.append("")

for field in type_def["fields"]:
Expand Down Expand Up @@ -328,7 +330,7 @@ def _generate_type_struct(self, type_name):
"size_t serialized_size() const {",
_indent("// %s" % ", ".join(fixed_fields)),
_indent("size_t _size = %d;" % fixed_size),
_indent(""),
"",
] + _indent(code_ss) + [
"}"]
code.extend(_indent(code_ss))
Expand Down Expand Up @@ -433,7 +435,7 @@ def _cpp_type(self, type_name: str) -> str:
raise RuntimeError("Can't get c++ type for %s" % type_name)

def _field_groups(self, fields):
groups = [FieldsGroup()]
groups = [FieldsGroup()] if len(fields) > 0 else []
for field in fields:
type_def = self._protocols.get_type(self._ctx["proto_name"], field["type"])
align = self._get_alignment(type_def)
Expand Down Expand Up @@ -478,7 +480,9 @@ def _serialize_field(self, field_name, field_type_def, level_n=0):
el_type_def = self._protocols.get_type(self._ctx["proto_name"], field_type_def["element_type"])
el_size = el_type_def.get("size")
el_align = self._get_alignment(el_type_def)
if el_size is not None and el_size % el_align == 0:
if el_size == 0:
pass
elif el_size is not None and el_size % el_align == 0:
# Vector of fixed size elements, optimize with single memcpy
c.append("_field_size = %d * %s.size();" % (el_size, field_name))
c.extend(self._memcpy_to_buf("%s[0]" % field_name, "_field_size"))
Expand Down Expand Up @@ -540,7 +544,9 @@ def _deserialize_field(self, field_name, field_type_def, level_n=0):
el_type_def = self._protocols.get_type(self._ctx["proto_name"], field_type_def["element_type"])
el_size = el_type_def.get("size")
el_align = self._get_alignment(el_type_def)
if el_size is not None and el_size % el_align == 0:
if el_size == 0:
pass
elif el_size is not None and el_size % el_align == 0:
# Vector or array of fixed size elements, optimize with single memcpy
c.append("_field_size = %d * %s.size();" % (el_size, field_name))
c.extend(self._memcpy_from_buf("%s[0]" % field_name, "_field_size"))
Expand All @@ -557,7 +563,9 @@ def _deserialize_field(self, field_name, field_type_def, level_n=0):
el_align = self._get_alignment(el_type_def)
c.append("%s.resize(*reinterpret_cast<const messgen::size_type *>(&_buf[_size]));" % field_name)
c.append("_size += sizeof(messgen::size_type);")
if el_size is not None and el_size % el_align == 0:
if el_size == 0:
pass
elif el_size is not None and el_size % el_align == 0:
# Vector or array of fixed size elements, optimize with single memcpy
c.append("_field_size = %d * %s.size();" % (el_size, field_name))
c.extend(self._memcpy_from_buf("%s[0]" % field_name, "_field_size"))
Expand All @@ -574,7 +582,9 @@ def _deserialize_field(self, field_name, field_type_def, level_n=0):
c.append("_field_size = *reinterpret_cast<const messgen::size_type *>(&_buf[_size]);")
c.append("%s = {_alloc.alloc<%s>(_field_size), _field_size};" % (field_name, el_c_type))
c.append("_size += sizeof(messgen::size_type);")
if el_size is not None and el_size % el_align == 0:
if el_size == 0:
pass
elif el_size is not None and el_size % el_align == 0:
# Vector or array of fixed size elements, optimize with single memcpy
if el_size != 1:
c.append("_field_size *= %d;" % el_size)
Expand All @@ -598,7 +608,7 @@ def _deserialize_field(self, field_name, field_type_def, level_n=0):
"for (size_t _i%d = 0; _i%d < _map_size%d; ++_i%d) {" % (level_n, level_n, level_n, level_n)))
c.append(_indent(_indent("%s _key%d;" % (key_c_type, level_n))))
c.append(_indent(_indent("%s _value%d;" % (value_c_type, level_n))))
c.append(_indent(_indent("")))
c.append("")
c.extend(_indent(
_indent(
self._deserialize_field("_key%d" % level_n, key_type_def, level_n + 1))))
Expand Down
1 change: 1 addition & 0 deletions messgen/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ def get_type(self, curr_proto_name, type_name) -> dict:
elif t["type_class"] == "struct":
sz = 0
fixed_size = True
t["fields"] = t.get("fields") if isinstance(t.get("fields"), list) else []
for i in t["fields"]:
it = self.get_type(curr_proto_name, i["type"])
isz = it.get("size")
Expand Down
9 changes: 9 additions & 0 deletions tests/cpp_nostl/CppNostlTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <messgen/test_proto/complex_struct_nostl.h>
#include <messgen/test_proto/struct_with_enum.h>
#include <messgen/test_proto/var_size_struct.h>
#include <messgen/test_proto/empty_struct.h>

#include <gtest/gtest.h>

Expand Down Expand Up @@ -96,3 +97,11 @@ TEST_F(CppNostlTest, ComplexStructNpstl) {

test_serialization(msg);
}

TEST_F(CppNostlTest, EmptyStruct) {
messgen::test_proto::empty_struct e{};
ASSERT_TRUE(e.IS_FLAT);
ASSERT_EQ(e.FLAT_SIZE, 0);
ASSERT_EQ(e.serialized_size(), 0);
test_serialization(e);
}
6 changes: 6 additions & 0 deletions tests/cpp_stl/CppTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <messgen/test_proto/struct_with_enum.h>
#include <messgen/test_proto/var_size_struct.h>
#include <messgen/test_proto/flat_struct.h>
#include <messgen/test_proto/complex_struct_with_empty.h>
#include <another_proto.h>

#include <gtest/gtest.h>
Expand Down Expand Up @@ -197,3 +198,8 @@ TEST_F(CppTest, TwoMsg) {
EXPECT_EQ(msg1, msg1c);
EXPECT_EQ(msg2, msg2c);
}

TEST_F(CppTest, ComplexStructWithEmpty) {
messgen::test_proto::complex_struct_with_empty e{};
test_serialization(e);
}
10 changes: 10 additions & 0 deletions tests/messages/messgen/test_proto/complex_struct_with_empty.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
type_class: struct
comment: "Struct with empty_struct in its fields"
fields:
- { name: "e", type: "empty_struct" }
- { name: "dynamic_array", type: "empty_struct[]" }
- { name: "static_array", type: "empty_struct[5]" }
- { name: "multi_array", type: "empty_struct[][5][]" }
- { name: "map_empty_by_int", type: "empty_struct{int32}" }
- { name: "map_vec_by_str", type: "empty_struct[]{string}" }
- { name: "array_of_size_zero", type: "int32[0]" }
3 changes: 3 additions & 0 deletions tests/messages/messgen/test_proto/empty_struct.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type_class: struct
comment: "Struct without data. May be used for heartbeat, command with no args, etc"
fields:

0 comments on commit 8545985

Please sign in to comment.