Use `absl::StringResizeAndOverwrite()` instead of `std::string::resize()` when the string is filled soon. Rename `ResizeStringAmortized()` to `StringResizeAmortized()` for consistency, and add `StringResizeAndOverwriteAmortized()`. Use `absl::AppendCordToString()`, which is now available, instead of a custom `riegeli::cord_internal::AppendCordToString()`. Cosmetics: for `std::string`, replace `&dest[i]` with `dest.data() + i` in remaining places. This relies on C++17. PiperOrigin-RevId: 858971838
diff --git a/riegeli/base/BUILD b/riegeli/base/BUILD index 0f89f66..ae37b53 100644 --- a/riegeli/base/BUILD +++ b/riegeli/base/BUILD
@@ -146,7 +146,9 @@ hdrs = ["string_utils.h"], deps = [ ":arithmetic", + ":assert", "@com_google_absl//absl/base:nullability", + "@com_google_absl//absl/strings:resize_and_overwrite", ], ) @@ -181,6 +183,7 @@ ":arithmetic", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/base:nullability", + "@com_google_absl//absl/strings:resize_and_overwrite", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:span", ], @@ -399,6 +402,7 @@ "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/base:nullability", "@com_google_absl//absl/strings:cord", + "@com_google_absl//absl/strings:resize_and_overwrite", "@com_google_absl//absl/strings:string_view", ], ) @@ -560,6 +564,7 @@ "@com_google_absl//absl/container:inlined_vector", "@com_google_absl//absl/meta:type_traits", "@com_google_absl//absl/strings:cord", + "@com_google_absl//absl/strings:resize_and_overwrite", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:span", ],
diff --git a/riegeli/base/chain.cc b/riegeli/base/chain.cc index 4dfaac1..009e606 100644 --- a/riegeli/base/chain.cc +++ b/riegeli/base/chain.cc
@@ -28,6 +28,7 @@ #include "absl/base/optimization.h" #include "absl/container/inlined_vector.h" #include "absl/strings/cord.h" +#include "absl/strings/resize_and_overwrite.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "riegeli/base/arithmetic.h" @@ -522,8 +523,10 @@ inline std::string Chain::ToString() const { if (begin_ == end_) return std::string(short_data()); std::string dest; - dest.resize(size_); - CopyToSlow(&dest[0]); + absl::StringResizeAndOverwrite(dest, size_, [&](char* data, size_t size) { + CopyToSlow(data); + return size; + }); return dest; } @@ -593,12 +596,15 @@ } void Chain::AppendTo(std::string& dest) const& { - const size_t size_before = dest.size(); - RIEGELI_CHECK_LE(size_, std::numeric_limits<size_t>::max() - size_before) + const size_t old_size = dest.size(); + RIEGELI_CHECK_LE(size_, std::numeric_limits<size_t>::max() - old_size) << "Failed precondition of Chain::AppendTo(string&): " "string size overflow"; - ResizeStringAmortized(dest, size_before + size_); - CopyTo(&dest[size_before]); + riegeli::StringResizeAndOverwriteAmortized(dest, old_size + size_, + [&](char* data, size_t size) { + CopyTo(data + old_size); + return size; + }); } void Chain::AppendTo(std::string& dest) && { @@ -616,12 +622,15 @@ } } } - const size_t size_before = dest.size(); - RIEGELI_CHECK_LE(size_, std::numeric_limits<size_t>::max() - size_before) + const size_t old_size = dest.size(); + RIEGELI_CHECK_LE(size_, std::numeric_limits<size_t>::max() - old_size) << "Failed precondition of Chain::AppendTo(string&): " "string size overflow"; - ResizeStringAmortized(dest, size_before + size_); - CopyTo(&dest[size_before]); + riegeli::StringResizeAndOverwriteAmortized(dest, old_size + size_, + [&](char* data, size_t size) { + CopyTo(data + old_size); + return size; + }); } void Chain::AppendTo(absl::Cord& dest) const& {
diff --git a/riegeli/base/cord_iterator_span.cc b/riegeli/base/cord_iterator_span.cc index 585ccc8..1107f3b 100644 --- a/riegeli/base/cord_iterator_span.cc +++ b/riegeli/base/cord_iterator_span.cc
@@ -22,6 +22,7 @@ #include "absl/base/nullability.h" #include "absl/base/optimization.h" #include "absl/strings/cord.h" +#include "absl/strings/resize_and_overwrite.h" #include "absl/strings/string_view.h" #include "riegeli/base/assert.h" #include "riegeli/base/string_utils.h" @@ -57,8 +58,11 @@ return chunk.substr(0, length); } scratch.clear(); - ResizeStringAmortized(scratch, length); - ReadSlow(iter, length, scratch.data()); + riegeli::StringResizeAndOverwriteAmortized(scratch, length, + [&](char* data, size_t size) { + ReadSlow(iter, size, data); + return size; + }); return scratch; } @@ -66,8 +70,10 @@ absl::Cord::CharIterator& iter = *iterator_; size_t length = length_; dest.clear(); - dest.resize(length); - Read(iter, length, dest.data()); + absl::StringResizeAndOverwrite(dest, length, [&](char* data, size_t size) { + Read(iter, size, data); + return size; + }); } } // namespace riegeli
diff --git a/riegeli/base/cord_utils.cc b/riegeli/base/cord_utils.cc index 9e4f492..239f104 100644 --- a/riegeli/base/cord_utils.cc +++ b/riegeli/base/cord_utils.cc
@@ -17,7 +17,6 @@ #include <stddef.h> #include <cstring> -#include <string> #include <utility> #include "absl/base/nullability.h" @@ -39,12 +38,6 @@ } } -void AppendCordToString(const absl::Cord& src, std::string& dest) { - const size_t old_size = dest.size(); - ResizeStringAmortized(dest, old_size + src.size()); - CopyCordToArray(src, &dest[old_size]); -} - absl::Cord MakeBlockyCord(absl::string_view src) { absl::Cord dest; AppendToBlockyCord(src, dest);
diff --git a/riegeli/base/cord_utils.h b/riegeli/base/cord_utils.h index 38ea2e2..c3611d2 100644 --- a/riegeli/base/cord_utils.h +++ b/riegeli/base/cord_utils.h
@@ -18,8 +18,6 @@ #include <stddef.h> #include <stdint.h> -#include <string> - #include "absl/base/nullability.h" #include "absl/numeric/bits.h" #include "absl/strings/cord.h" @@ -75,9 +73,6 @@ // `nullptr` only if `src.empty()`. void CopyCordToArray(const absl::Cord& src, char* absl_nullable dest); -// Appends `src` to `dest`. -void AppendCordToString(const absl::Cord& src, std::string& dest); - // Variants of `absl::Cord` operations with different block sizing tradeoffs: // * `MakeBlockyCord(src)` is like `absl::Cord(src)`. // * `AssignToBlockyCord(src, dest)` is like `dest = src`.
diff --git a/riegeli/base/string_utils.cc b/riegeli/base/string_utils.cc index cf42af2..ea77059 100644 --- a/riegeli/base/string_utils.cc +++ b/riegeli/base/string_utils.cc
@@ -23,18 +23,14 @@ ABSL_POINTERS_DEFAULT_NONNULL -namespace riegeli { +namespace riegeli::string_utils_internal { -void ResizeStringAmortized(std::string& dest, size_t new_size) { - if (new_size > dest.capacity()) { - dest.reserve( - dest.capacity() == std::string().capacity() - ? new_size - : UnsignedMax(new_size, - UnsignedMin(dest.capacity() + dest.capacity() / 2, - dest.max_size()))); - } - dest.resize(new_size); +void ReserveAmortized(std::string& dest, size_t new_size) { + dest.reserve(dest.capacity() == std::string().capacity() + ? new_size + : UnsignedMax(new_size, UnsignedMin(dest.capacity() + + dest.capacity() / 2, + dest.max_size()))); } -} // namespace riegeli +} // namespace riegeli::string_utils_internal
diff --git a/riegeli/base/string_utils.h b/riegeli/base/string_utils.h index d8a799a..25c6d99 100644 --- a/riegeli/base/string_utils.h +++ b/riegeli/base/string_utils.h
@@ -18,16 +18,43 @@ #include <stddef.h> #include <string> +#include <utility> #include "absl/base/nullability.h" +#include "absl/strings/resize_and_overwrite.h" +#include "riegeli/base/assert.h" ABSL_POINTERS_DEFAULT_NONNULL namespace riegeli { -// Resizes `dest` to `new_size`, ensuring that repeated growth has the cost -// proportional to the final size. New contents are unspecified. -void ResizeStringAmortized(std::string& dest, size_t new_size); +namespace string_utils_internal { + +void ReserveAmortized(std::string& dest, size_t new_size); + +} // namespace string_utils_internal + +// Like `std::string::resize()`, ensuring that repeated growth has the cost +// proportional to the final size. +inline void StringResizeAmortized(std::string& dest, size_t new_size) { + if (new_size > dest.capacity()) { + string_utils_internal::ReserveAmortized(dest, new_size); + } + RIEGELI_ASSUME_GE(dest.capacity(), new_size); + dest.resize(new_size); +} + +// Like `absl::StringResizeAndOverwrite()`, ensuring that repeated growth has +// the cost proportional to the final size. +template <typename Op> +inline void StringResizeAndOverwriteAmortized(std::string& dest, + size_t new_size, Op op) { + if (new_size > dest.capacity()) { + string_utils_internal::ReserveAmortized(dest, new_size); + } + RIEGELI_ASSUME_GE(dest.capacity(), new_size); + return absl::StringResizeAndOverwrite(dest, new_size, std::move(op)); +} } // namespace riegeli
diff --git a/riegeli/base/unicode.cc b/riegeli/base/unicode.cc index 877dd4c..3cfcbbe 100644 --- a/riegeli/base/unicode.cc +++ b/riegeli/base/unicode.cc
@@ -28,6 +28,7 @@ #include "absl/base/nullability.h" #include "absl/base/optimization.h" +#include "absl/strings/resize_and_overwrite.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "riegeli/base/arithmetic.h" @@ -49,7 +50,7 @@ if (ABSL_PREDICT_FALSE(dest_size == 0)) return false; dest.resize(IntCast<size_t>(dest_size)); MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, src.data(), - IntCast<int>(src.size()), &dest[0], dest_size); + IntCast<int>(src.size()), dest.data(), dest_size); return true; } @@ -64,10 +65,13 @@ CP_UTF8, WC_ERR_INVALID_CHARS, src.data(), IntCast<int>(src.size()), nullptr, 0, nullptr, nullptr); if (ABSL_PREDICT_FALSE(dest_size == 0)) return false; - dest.resize(IntCast<size_t>(dest_size)); - WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src.data(), - IntCast<int>(src.size()), &dest[0], dest_size, nullptr, - nullptr); + absl::StringResizeAndOverwrite( + dest, IntCast<size_t>(dest_size), [&](char* data, size_t size) { + WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src.data(), + IntCast<int>(src.size()), data, IntCast<int>(size), + nullptr, nullptr); + return size; + }); return true; } @@ -77,10 +81,13 @@ const int dest_size = WideCharToMultiByte(CP_UTF8, 0, src.data(), SaturatingIntCast<int>(src.size()), nullptr, 0, nullptr, nullptr); - dest.resize(IntCast<size_t>(dest_size)); - WideCharToMultiByte(CP_UTF8, 0, src.data(), - SaturatingIntCast<int>(src.size()), &dest[0], dest_size, - nullptr, nullptr); + absl::StringResizeAndOverwrite( + dest, IntCast<size_t>(dest_size), [&](char* data, size_t size) { + WideCharToMultiByte(CP_UTF8, 0, src.data(), + SaturatingIntCast<int>(src.size()), data, + IntCast<int>(size), nullptr, nullptr); + return size; + }); return dest; }
diff --git a/riegeli/bytes/BUILD b/riegeli/bytes/BUILD index 1b14a10..5152c86 100644 --- a/riegeli/bytes/BUILD +++ b/riegeli/bytes/BUILD
@@ -146,6 +146,7 @@ "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:cord", + "@com_google_absl//absl/strings:resize_and_overwrite", "@com_google_absl//absl/strings:string_view", ], )
diff --git a/riegeli/bytes/read_all.cc b/riegeli/bytes/read_all.cc index d61e574..6357d04 100644 --- a/riegeli/bytes/read_all.cc +++ b/riegeli/bytes/read_all.cc
@@ -25,6 +25,7 @@ #include "absl/base/optimization.h" #include "absl/status/status.h" #include "absl/strings/cord.h" +#include "absl/strings/resize_and_overwrite.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "riegeli/base/arithmetic.h" @@ -100,16 +101,20 @@ return absl::OkStatus(); } size_t remaining_max_length = max_length; - const size_t dest_pos = dest.size(); - if (src.available() < dest.capacity() - dest_pos) { + const size_t old_size = dest.size(); + if (src.available() < dest.capacity() - old_size) { // Try to fill all remaining space in `dest`, to avoid copying through the // `Chain` in case the remaining length is smaller. const size_t length = - UnsignedMin(dest.capacity() - dest_pos, remaining_max_length); - dest.resize(dest_pos + length); + UnsignedMin(dest.capacity() - old_size, remaining_max_length); + bool read_ok; size_t length_read; - if (!src.Read(length, &dest[dest_pos], &length_read)) { - dest.erase(dest_pos + length_read); + absl::StringResizeAndOverwrite( + dest, old_size + length, [&](char* data, size_t size) { + read_ok = src.Read(size - old_size, data + old_size, &length_read); + return old_size + length_read; + }); + if (!read_ok) { if (ABSL_PREDICT_FALSE(!src.ok())) return src.status(); return absl::OkStatus(); }
diff --git a/riegeli/bytes/reader.cc b/riegeli/bytes/reader.cc index d231095..1e0bcd7 100644 --- a/riegeli/bytes/reader.cc +++ b/riegeli/bytes/reader.cc
@@ -385,14 +385,15 @@ RIEGELI_ASSERT_LE(length, std::numeric_limits<size_t>::max() - dest.size()) << "Failed precondition of Reader::ReadSlow(string&): " "string size overflow"; - const size_t dest_pos = dest.size(); - ResizeStringAmortized(dest, dest_pos + length); - size_t length_read; - if (ABSL_PREDICT_FALSE(!ReadSlow(length, &dest[dest_pos], length_read))) { - dest.erase(dest_pos + length_read); - return false; - } - return true; + const size_t old_size = dest.size(); + bool read_ok; + riegeli::StringResizeAndOverwriteAmortized( + dest, old_size + length, [&](char* data, size_t size) { + size_t length_read; + read_ok = ReadSlow(size - old_size, data + old_size, length_read); + return old_size + length_read; + }); + return read_ok; } bool Reader::ReadSlow(size_t length, std::string& dest, size_t& length_read) { @@ -623,11 +624,14 @@ std::numeric_limits<size_t>::max() - dest.size()) << "Failed precondition of Reader::ReadSomeSlow(string&): " "string size overflow"; - const size_t dest_pos = dest.size(); - ResizeStringAmortized(dest, dest_pos + max_length); - size_t length_read; - const bool read_ok = ReadSomeSlow(max_length, &dest[dest_pos], length_read); - dest.erase(dest_pos + length_read); + const size_t old_size = dest.size(); + bool read_ok; + riegeli::StringResizeAndOverwriteAmortized( + dest, old_size + max_length, [&](char* data, size_t size) { + size_t length_read; + read_ok = ReadSomeSlow(size - old_size, data + old_size, length_read); + return old_size + length_read; + }); return read_ok; }
diff --git a/riegeli/bytes/resizable_writer.h b/riegeli/bytes/resizable_writer.h index 3afd257..2e70004 100644 --- a/riegeli/bytes/resizable_writer.h +++ b/riegeli/bytes/resizable_writer.h
@@ -327,7 +327,7 @@ template <typename Alloc = std::allocator<char>> struct StringResizableTraits { using Resizable = std::basic_string<char, std::char_traits<char>, Alloc>; - static char* Data(Resizable& dest) { return &dest[0]; } + static char* Data(Resizable& dest) { return dest.data(); } static size_t Size(const Resizable& dest) { return dest.size(); } static constexpr bool kIsStable = false; static bool Resize(Resizable& dest, size_t new_size, size_t used_size) {
diff --git a/riegeli/bytes/string_writer.cc b/riegeli/bytes/string_writer.cc index d08e9f0..af4ece4 100644 --- a/riegeli/bytes/string_writer.cc +++ b/riegeli/bytes/string_writer.cc
@@ -65,7 +65,7 @@ RIEGELI_ASSERT(!uses_secondary_buffer()) << "Failed precondition in StringWriterBase::MakeDestBuffer(): " "secondary buffer is used"; - set_buffer(&dest[0], dest.size(), cursor_index); + set_buffer(dest.data(), dest.size(), cursor_index); set_start_pos(0); } @@ -170,7 +170,7 @@ const size_t new_cursor_index = cursor_index + src.size(); if (new_cursor_index <= dest.capacity()) { if (ABSL_PREDICT_FALSE(new_cursor_index <= dest.size())) { - std::memcpy(&dest[cursor_index], src.data(), src.size()); + std::memcpy(dest.data() + cursor_index, src.data(), src.size()); } else { dest.erase(cursor_index); // TODO: When `absl::string_view` becomes C++17 @@ -210,7 +210,7 @@ const size_t new_cursor_index = cursor_index + src.size(); if (new_cursor_index <= dest.capacity()) { if (ABSL_PREDICT_FALSE(new_cursor_index <= dest.size())) { - src.CopyTo(&dest[cursor_index]); + src.CopyTo(dest.data() + cursor_index); } else { dest.erase(cursor_index); src.AppendTo(dest); @@ -248,7 +248,7 @@ const size_t new_cursor_index = cursor_index + src.size(); if (new_cursor_index <= dest.capacity()) { if (ABSL_PREDICT_FALSE(new_cursor_index <= dest.size())) { - src.CopyTo(&dest[cursor_index]); + src.CopyTo(dest.data() + cursor_index); } else { dest.erase(cursor_index); std::move(src).AppendTo(dest); @@ -286,10 +286,10 @@ const size_t new_cursor_index = cursor_index + src.size(); if (new_cursor_index <= dest.capacity()) { if (ABSL_PREDICT_FALSE(new_cursor_index <= dest.size())) { - cord_internal::CopyCordToArray(src, &dest[cursor_index]); + cord_internal::CopyCordToArray(src, dest.data() + cursor_index); } else { dest.erase(cursor_index); - cord_internal::AppendCordToString(src, dest); + absl::AppendCordToString(src, &dest); } GrowDestToCapacityAndMakeBuffer(dest, new_cursor_index); return true; @@ -324,10 +324,10 @@ const size_t new_cursor_index = cursor_index + src.size(); if (new_cursor_index <= dest.capacity()) { if (ABSL_PREDICT_FALSE(new_cursor_index <= dest.size())) { - cord_internal::CopyCordToArray(src, &dest[cursor_index]); + cord_internal::CopyCordToArray(src, dest.data() + cursor_index); } else { dest.erase(cursor_index); - cord_internal::AppendCordToString(src, dest); + absl::AppendCordToString(src, &dest); } GrowDestToCapacityAndMakeBuffer(dest, new_cursor_index); return true; @@ -362,7 +362,7 @@ const size_t new_cursor_index = cursor_index + IntCast<size_t>(src.size()); if (new_cursor_index <= dest.capacity()) { if (ABSL_PREDICT_FALSE(new_cursor_index <= dest.size())) { - std::memset(&dest[cursor_index], src.fill(), + std::memset(dest.data() + cursor_index, src.fill(), IntCast<size_t>(src.size())); } else { dest.erase(cursor_index);
diff --git a/riegeli/bytes/string_writer.h b/riegeli/bytes/string_writer.h index 0f371d0..334c9f3 100644 --- a/riegeli/bytes/string_writer.h +++ b/riegeli/bytes/string_writer.h
@@ -357,7 +357,7 @@ void Done(StringWriter& self) { if (uses_buffer_) { std::string& dest = *self.dest_; - self.set_buffer(&dest[0], dest.size(), start_to_cursor_); + self.set_buffer(dest.data(), dest.size(), start_to_cursor_); } }
diff --git a/riegeli/messages/serialize_message.cc b/riegeli/messages/serialize_message.cc index ba7a21e..942586d 100644 --- a/riegeli/messages/serialize_message.cc +++ b/riegeli/messages/serialize_message.cc
@@ -85,9 +85,9 @@ << "Failed to serialize message of type " << src.GetTypeName() << ": SerializeWithCachedSizes() failed for an unknown reason"; RIEGELI_ASSERT_EQ(IntCast<size_t>(coded_stream.ByteCount()), size) - << "Byte size calculation and serialization were inconsistent. This " - "may indicate a bug in protocol buffers or it may be caused by " - "concurrent modification of " + << "Byte size calculation and serialization were inconsistent. " + "This may indicate a bug in protocol buffers " + "or it may be caused by concurrent modification of " << src.GetTypeName(); return absl::OkStatus(); } @@ -107,9 +107,9 @@ << src.GetTypeName() << " was modified concurrently during serialization"; RIEGELI_ASSERT_EQ(PtrDistance(dest.cursor(), cursor), size) - << "Byte size calculation and serialization were inconsistent. This " - "may indicate a bug in protocol buffers or it may be caused by " - "concurrent modification of " + << "Byte size calculation and serialization were inconsistent. " + "This may indicate a bug in protocol buffers " + "or it may be caused by concurrent modification of " << src.GetTypeName(); dest.set_cursor(cursor); return absl::OkStatus(); @@ -133,9 +133,9 @@ << src.GetTypeName() << " was modified concurrently during serialization"; RIEGELI_ASSERT_EQ(PtrDistance(dest.cursor(), cursor), size) - << "Byte size calculation and serialization were inconsistent. This " - "may indicate a bug in protocol buffers or it may be caused by " - "concurrent modification of " + << "Byte size calculation and serialization were inconsistent. " + "This may indicate a bug in protocol buffers " + "or it may be caused by concurrent modification of " << src.GetTypeName(); return absl::OkStatus(); } @@ -222,30 +222,35 @@ return FailSizeOverflow(src, size); } dest.clear(); - ResizeStringAmortized(dest, size); - if (options.deterministic() == std::nullopt) { - // Creating a string, which is necessarily flat. - // `SerializeWithCachedSizesToArray()` is faster than - // `SerializeWithCachedSizes()`. - char* const cursor = - reinterpret_cast<char*>(src.SerializeWithCachedSizesToArray( - reinterpret_cast<uint8_t*>(&dest[0]))); - RIEGELI_ASSERT_EQ(src.ByteSizeLong(), size) - << src.GetTypeName() - << " was modified concurrently during serialization"; - RIEGELI_ASSERT_EQ(PtrDistance(dest.data(), cursor), size) - << "Byte size calculation and serialization were inconsistent. This " - "may indicate a bug in protocol buffers or it may be caused by " - "concurrent modification of " - << src.GetTypeName(); - return absl::OkStatus(); - } - riegeli::ArrayWriter writer(&dest[0], size); - const absl::Status status = - SerializeMessageUsingStream(src, writer, options.deterministic(), size); - RIEGELI_EVAL_ASSERT(writer.Close()) << "ArrayWriter has no reason to fail " - "if the size does not overflow: " - << writer.status(); + absl::Status status; + riegeli::StringResizeAndOverwriteAmortized( + dest, size, [&](char* data, size_t size) { + if (options.deterministic() == std::nullopt) { + // Creating a string, which is necessarily flat. + // `SerializeWithCachedSizesToArray()` is faster than + // `SerializeWithCachedSizes()`. + char* const cursor = + reinterpret_cast<char*>(src.SerializeWithCachedSizesToArray( + reinterpret_cast<uint8_t*>(data))); + RIEGELI_ASSERT_EQ(src.ByteSizeLong(), size) + << src.GetTypeName() + << " was modified concurrently during serialization"; + RIEGELI_ASSERT_EQ(PtrDistance(data, cursor), size) + << "Byte size calculation and serialization were inconsistent. " + "This may indicate a bug in protocol buffers " + "or it may be caused by concurrent modification of " + << src.GetTypeName(); + return size; + } + riegeli::ArrayWriter writer(data, size); + status = SerializeMessageUsingStream(src, writer, + options.deterministic(), size); + RIEGELI_EVAL_ASSERT(writer.Close()) + << "ArrayWriter has no reason to fail " + "if the size does not overflow: " + << writer.status(); + return writer.written().size(); + }); return status; } @@ -272,9 +277,9 @@ << src.GetTypeName() << " was modified concurrently during serialization"; RIEGELI_ASSERT_EQ(PtrDistance(data, cursor), size) - << "Byte size calculation and serialization were inconsistent. This " - "may indicate a bug in protocol buffers or it may be caused by " - "concurrent modification of " + << "Byte size calculation and serialization were inconsistent. " + "This may indicate a bug in protocol buffers " + "or it may be caused by concurrent modification of " << src.GetTypeName(); return absl::OkStatus(); } @@ -312,9 +317,9 @@ << src.GetTypeName() << " was modified concurrently during serialization"; RIEGELI_ASSERT_EQ(PtrDistance(buffer.data(), cursor), size) - << "Byte size calculation and serialization were inconsistent. This " - "may indicate a bug in protocol buffers or it may be caused by " - "concurrent modification of " + << "Byte size calculation and serialization were inconsistent. " + "This may indicate a bug in protocol buffers " + "or it may be caused by concurrent modification of " << src.GetTypeName(); return absl::OkStatus(); } @@ -358,9 +363,9 @@ << src.GetTypeName() << " was modified concurrently during serialization"; RIEGELI_ASSERT_EQ(PtrDistance(buffer.data(), cursor), size) - << "Byte size calculation and serialization were inconsistent. This " - "may indicate a bug in protocol buffers or it may be caused by " - "concurrent modification of " + << "Byte size calculation and serialization were inconsistent. " + "This may indicate a bug in protocol buffers " + "or it may be caused by concurrent modification of " << src.GetTypeName(); dest.Append(std::move(buffer)); return absl::OkStatus();
diff --git a/riegeli/records/record_position.cc b/riegeli/records/record_position.cc index 8fc06ec..3d62b1b 100644 --- a/riegeli/records/record_position.cc +++ b/riegeli/records/record_position.cc
@@ -81,9 +81,9 @@ bool RecordPosition::FromBytes(absl::string_view serialized) { if (serialized.size() == 2 * sizeof(uint64_t)) { // Reading the old format is temporarily supported too. - const uint64_t chunk_begin = ReadBigEndian<uint64_t>(&serialized[0]); + const uint64_t chunk_begin = ReadBigEndian<uint64_t>(serialized.data()); const uint64_t record_index = - ReadBigEndian<uint64_t>(&serialized[sizeof(uint64_t)]); + ReadBigEndian<uint64_t>(serialized.data() + sizeof(uint64_t)); if (ABSL_PREDICT_FALSE(record_index > std::numeric_limits<uint64_t>::max() - chunk_begin)) { return false;