diff --git a/MODULE.bazel b/MODULE.bazel index 73c6059..ba2f84d 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,6 +1,6 @@ module( name = "phaser", - version = "2.1.0" + version = "2.1.1" ) bazel_dep(name = "bazel_skylib", version = "1.9.0") @@ -17,17 +17,9 @@ bazel_dep(name = "rules_shell", version = "0.8.0") bazel_dep(name = "rules_pkg", version = "1.0.1") bazel_dep(name = "zlib", version = "1.3.1.bcr.5") -bazel_dep(name = "cpp_toolbelt", version = "2.1.2") +bazel_dep(name = "cpp_toolbelt", version = "2.1.5") bazel_dep(name = "coroutines", version = "3.3.2") -# Until cpp_toolbelt 2.1.3 is published to BCR, pin the bounds-checking fixes -# from the bounds_fixes branch. Remove this override once the release lands. -git_override( - module_name = "cpp_toolbelt", - remote = "https://github.com/dallison/cpp_toolbelt.git", - commit = "f69cb51", -) - # protobuf pulls an older rules_go via gazelle; Bazel 9 needs a current rules_go. single_version_override( module_name = "rules_go", diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 85d57b1..79ca9f3 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -79,6 +79,8 @@ "https://bcr.bazel.build/modules/buildozer/8.5.1/source.json": "e3386e6ff4529f2442800dee47ad28d3e6487f36a1f75ae39ae56c70f0cd2fbd", "https://bcr.bazel.build/modules/coroutines/3.3.2/MODULE.bazel": "ad1395ae9758ee5d113acab755b4d972c368c4dab66513bfe31423136f3ee608", "https://bcr.bazel.build/modules/coroutines/3.3.2/source.json": "fb47a4c3e13d730a1a58ed6a34add8f6aaeef655a47d0f179427f71bf58ba150", + "https://bcr.bazel.build/modules/cpp_toolbelt/2.1.5/MODULE.bazel": "6e09603c35d27d12d9d1ad33157d82acd2d0e87ff8f957b7efb257b2a7a3ece6", + "https://bcr.bazel.build/modules/cpp_toolbelt/2.1.5/source.json": "22d3adfbd3e6ce87f688d14866b93c6158d3f704919022c41528c8228e7b8396", "https://bcr.bazel.build/modules/gawk/5.3.2.bcr.1/MODULE.bazel": "cdf8cbe5ee750db04b78878c9633cc76e80dcf4416cbe982ac3a9222f80713c8", "https://bcr.bazel.build/modules/gawk/5.3.2.bcr.1/source.json": "fa7b512dfcb5eafd90ce3959cf42a2a6fe96144ebbb4b3b3928054895f2afac2", "https://bcr.bazel.build/modules/gazelle/0.45.0/MODULE.bazel": "ecd19ebe9f8e024e1ccffb6d997cc893a974bcc581f1ae08f386bdd448b10687", diff --git a/phaser/runtime/fields.h b/phaser/runtime/fields.h index 5d81e98..47fdc83 100644 --- a/phaser/runtime/fields.h +++ b/phaser/runtime/fields.h @@ -651,7 +651,7 @@ class StringField : public Field, public StringFieldFacade { StringField& operator=(const char* s) { ::toolbelt::PayloadBuffer::SetString( GetBufferAddr(), std::string_view(s, std::strlen(s)), - GetMessageBinaryStart() + relative_binary_offset_); + StringHeaderOffset()); return *this; } @@ -679,34 +679,31 @@ class StringField : public Field, public StringFieldFacade { template void Set(Str s) { - ::toolbelt::PayloadBuffer::SetString( - GetBufferAddr(), s, GetMessageBinaryStart() + relative_binary_offset_); + ::toolbelt::PayloadBuffer::SetString(GetBufferAddr(), s, + StringHeaderOffset()); } void Set(const char* data, size_t size) { ::toolbelt::PayloadBuffer::SetString( - GetBufferAddr(), std::string_view(data, size), - GetMessageBinaryStart() + relative_binary_offset_); + GetBufferAddr(), std::string_view(data, size), StringHeaderOffset()); } void SetNoCopy(const void* data) { toolbelt::StringHeader* header = - GetRuntime()->ToAddress( - GetMessageBinaryStart() + relative_binary_offset_); + GetRuntime()->ToAddress(StringHeaderOffset()); *header = GetRuntime()->ToOffset(data); } void Clear() { - ::toolbelt::PayloadBuffer::ClearString( - GetBufferAddr(), GetMessageBinaryStart() + relative_binary_offset_); + ::toolbelt::PayloadBuffer::ClearString(GetBufferAddr(), StringHeaderOffset()); } // Allocate space for the given size for the string and return the // starting address. absl::Span Allocate(size_t size, bool clear = false) { - return ::toolbelt::PayloadBuffer::AllocateString( - GetBufferAddr(), size, - GetMessageBinaryStart() + relative_binary_offset_, clear); + return ::toolbelt::PayloadBuffer::AllocateString(GetBufferAddr(), size, + StringHeaderOffset(), + clear); } size_t size() const { @@ -744,8 +741,8 @@ class StringField : public Field, public StringFieldFacade { if (!s.ok()) { return s.status(); } - ::toolbelt::PayloadBuffer::SetString( - GetBufferAddr(), *s, GetMessageBinaryStart() + relative_binary_offset_); + ::toolbelt::PayloadBuffer::SetString(GetBufferAddr(), *s, + StringHeaderOffset()); return absl::OkStatus(); } @@ -768,6 +765,15 @@ class StringField : public Field, public StringFieldFacade { return Message::GetMessageBinaryStart(this, source_offset_); } + ::toolbelt::BufferOffset StringHeaderOffset() const { + int32_t offset = FindFieldOffset(source_offset_); + if (offset < 0) { + return GetMessageBinaryStart() + relative_binary_offset_; + } + return GetMessageBinaryStart() + + static_cast<::toolbelt::BufferOffset>(offset); + } + uint32_t source_offset_; ::toolbelt::BufferOffset relative_binary_offset_; }; diff --git a/phaser/runtime/message.h b/phaser/runtime/message.h index af38aa8..4b47f3a 100644 --- a/phaser/runtime/message.h +++ b/phaser/runtime/message.h @@ -472,18 +472,14 @@ struct MessageRuntime { // an underflow read. size_t AllocatedCapacity(toolbelt::BufferOffset data_offset, size_t elem_size) const { - if (elem_size == 0 || - data_offset < sizeof(toolbelt::BufferOffset)) { + if (elem_size == 0 || data_offset == 0 || pb == nullptr) { return 0; } - const toolbelt::BufferOffset size_offset = - data_offset - - static_cast(sizeof(toolbelt::BufferOffset)); - const auto* size_word = ToAddress(size_offset); - if (size_word == nullptr) { + uint32_t* block = pb->ToAddress(data_offset); + if (block == nullptr) { return 0; } - return *size_word / elem_size; + return ::toolbelt::PayloadBuffer::DecodeSize(block) / elem_size; } template diff --git a/phaser/runtime/vectors.h b/phaser/runtime/vectors.h index 4c21351..0fbf8a2 100644 --- a/phaser/runtime/vectors.h +++ b/phaser/runtime/vectors.h @@ -1197,7 +1197,7 @@ class MessageVectorField : public Field { ::toolbelt::BufferOffset absolute_binary_offset = GetRuntime()->ToOffset(binary); ::toolbelt::PayloadBuffer::VectorPush<::toolbelt::BufferOffset>( - GetBufferAddr(), Header(), absolute_binary_offset); + GetBufferAddr(), ResolvedVectorHeader(), absolute_binary_offset); T result(GetRuntime(), absolute_binary_offset); result.template InstallMetadata(); return result; @@ -1208,10 +1208,10 @@ class MessageVectorField : public Field { T Mutable(size_t index) { if (index >= size()) { ::toolbelt::PayloadBuffer::VectorResize<::toolbelt::BufferOffset>( - GetBufferAddr(), Header(), index + 1); + GetBufferAddr(), ResolvedVectorHeader(), index + 1); } - auto hdr = Header(); + auto hdr = ResolvedVectorHeader(); ::toolbelt::BufferOffset* data = GetRuntime()->template ToAddress<::toolbelt::BufferOffset>(hdr->data); if (data[index] == 0) { @@ -1220,7 +1220,7 @@ class MessageVectorField : public Field { ::toolbelt::BufferOffset absolute_binary_offset = GetRuntime()->ToOffset(binary); - hdr = Header(); + hdr = ResolvedVectorHeader(); data = GetRuntime()->template ToAddress<::toolbelt::BufferOffset>(hdr->data); data[index] = absolute_binary_offset; @@ -1234,9 +1234,9 @@ class MessageVectorField : public Field { void SetOffset(int index, toolbelt::BufferOffset offset) { if (static_cast(index) >= size()) { ::toolbelt::PayloadBuffer::VectorResize<::toolbelt::BufferOffset>( - GetBufferAddr(), Header(), static_cast(index) + 1); + GetBufferAddr(), ResolvedVectorHeader(), static_cast(index) + 1); } - auto hdr = Header(); + auto hdr = ResolvedVectorHeader(); ::toolbelt::BufferOffset* data = GetRuntime()->template ToAddress<::toolbelt::BufferOffset>(hdr->data); if (data[index] != 0) { @@ -1253,12 +1253,12 @@ class MessageVectorField : public Field { result.reserve(n); Clear(); ::toolbelt::PayloadBuffer::VectorResize<::toolbelt::BufferOffset>( - GetBufferAddr(), Header(), n); + GetBufferAddr(), ResolvedVectorHeader(), n); // Allocate memory for n messages in the payload buffer. std::vector addrs = ::toolbelt::PayloadBuffer::AllocateMany( GetBufferAddr(), T::BinarySize(), static_cast(n), true); - toolbelt::VectorHeader* hdr = Header(); + toolbelt::VectorHeader* hdr = ResolvedVectorHeader(); ::toolbelt::BufferOffset* data = GetRuntime()->template ToAddress<::toolbelt::BufferOffset>(hdr->data); @@ -1279,14 +1279,14 @@ class MessageVectorField : public Field { void reserve(size_t n) { ::toolbelt::PayloadBuffer::VectorReserve<::toolbelt::BufferOffset>( - GetBufferAddr(), Header(), n); + GetBufferAddr(), ResolvedVectorHeader(), n); } void resize(size_t n) { const size_t old_size = size(); if (n < old_size) { for (size_t i = n; i < old_size; ++i) { - auto hdr = Header(); + auto hdr = ResolvedVectorHeader(); auto data = GetRuntime()->template ToAddress<::toolbelt::BufferOffset>( hdr->data); const ::toolbelt::BufferOffset offset = data[i]; @@ -1297,7 +1297,7 @@ class MessageVectorField : public Field { } } ::toolbelt::PayloadBuffer::VectorResize<::toolbelt::BufferOffset>( - GetBufferAddr(), Header(), n); + GetBufferAddr(), ResolvedVectorHeader(), n); for (size_t i = old_size; i < n; ++i) { (void)Mutable(i); } @@ -1370,7 +1370,7 @@ class MessageVectorField : public Field { } void Clear() { - auto hdr = Header(); + auto hdr = ResolvedVectorHeader(); auto data = GetRuntime()->template ToAddress<::toolbelt::BufferOffset>(hdr->data); for (uint32_t i = 0; i < hdr->num_elements; i++) { @@ -1381,7 +1381,7 @@ class MessageVectorField : public Field { GetBuffer()->Free(GetRuntime()->ToAddress(data[i])); } ::toolbelt::PayloadBuffer::VectorClear<::toolbelt::BufferOffset>( - GetBufferAddr(), Header()); + GetBufferAddr(), ResolvedVectorHeader()); } void clear() { Clear(); } @@ -1548,6 +1548,14 @@ class MessageVectorField : public Field { GetMessageBinaryStart() + relative_offset); } + toolbelt::VectorHeader* ResolvedVectorHeader() const { + int32_t offset = FindFieldOffset(source_offset_); + if (offset < 0) { + offset = static_cast(relative_binary_offset_); + } + return Header(static_cast(offset)); + } + ::toolbelt::BufferOffset BaseOffset() const { int32_t offset = FindFieldOffset(source_offset_); if (offset < 0) { @@ -1806,7 +1814,7 @@ class StringVectorField : public Field { // Add an offset for the new string to the binary. ::toolbelt::PayloadBuffer::VectorPush<::toolbelt::BufferOffset>( - GetBufferAddr(), Header(), hdr_offset); + GetBufferAddr(), ResolvedVectorHeader(), hdr_offset); } template @@ -1833,10 +1841,10 @@ class StringVectorField : public Field { void Set(size_t index, Str s) { if (index >= size()) { ::toolbelt::PayloadBuffer::VectorResize<::toolbelt::BufferOffset>( - GetBufferAddr(), Header(), index + 1); + GetBufferAddr(), ResolvedVectorHeader(), index + 1); } - auto hdr = Header(); + auto hdr = ResolvedVectorHeader(); ::toolbelt::BufferOffset* data = GetRuntime()->template ToAddress<::toolbelt::BufferOffset>(hdr->data); if (data[index] == 0) { @@ -1845,7 +1853,7 @@ class StringVectorField : public Field { GetBufferAddr(), sizeof(toolbelt::StringHeader)); ::toolbelt::BufferOffset hdr_offset = GetRuntime()->ToOffset(str_hdr); - hdr = Header(); + hdr = ResolvedVectorHeader(); data = GetRuntime()->template ToAddress<::toolbelt::BufferOffset>(hdr->data); data[index] = hdr_offset; @@ -1862,14 +1870,14 @@ class StringVectorField : public Field { void reserve(size_t n) { ::toolbelt::PayloadBuffer::VectorReserve<::toolbelt::BufferOffset>( - GetBufferAddr(), Header(), n); + GetBufferAddr(), ResolvedVectorHeader(), n); } void resize(size_t n) { const size_t old_size = size(); if (n < old_size) { for (size_t i = n; i < old_size; ++i) { - auto hdr = Header(); + auto hdr = ResolvedVectorHeader(); auto data = GetRuntime()->template ToAddress<::toolbelt::BufferOffset>( hdr->data); const ::toolbelt::BufferOffset offset = data[i]; @@ -1881,7 +1889,7 @@ class StringVectorField : public Field { } } ::toolbelt::PayloadBuffer::VectorResize<::toolbelt::BufferOffset>( - GetBufferAddr(), Header(), n); + GetBufferAddr(), ResolvedVectorHeader(), n); } void resize(size_t n, std::string_view value) { const std::string value_copy(value); @@ -1955,7 +1963,7 @@ class StringVectorField : public Field { } void Clear() { - auto hdr = Header(); + auto hdr = ResolvedVectorHeader(); auto data = GetRuntime()->template ToAddress<::toolbelt::BufferOffset>(hdr->data); for (size_t i = 0; i < hdr->num_elements; ++i) { @@ -1967,7 +1975,7 @@ class StringVectorField : public Field { .Clear(); } ::toolbelt::PayloadBuffer::VectorClear<::toolbelt::BufferOffset>( - GetBufferAddr(), Header()); + GetBufferAddr(), ResolvedVectorHeader()); } void clear() { Clear(); } // STL compatibility. @@ -2095,6 +2103,14 @@ class StringVectorField : public Field { GetMessageBinaryStart() + relative_offset); } + toolbelt::VectorHeader* ResolvedVectorHeader() const { + int32_t offset = FindFieldOffset(source_offset_); + if (offset < 0) { + offset = static_cast(relative_binary_offset_); + } + return Header(static_cast(offset)); + } + const std::shared_ptr& GetRuntime() const { return Message::GetRuntime(this, source_offset_); }