aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-03-08 01:05:44 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-03-08 01:05:44 +0000
commit70e0cc16c408f2641e22e6f0e628f6c6d1121185 (patch)
treef0d3f05c18afd04b9824b485585518fe06641ee1
parentf1f90d5cc383ebe0cce0e3c79b8d4085d3b545c0 (diff)
parent0af506eab5a6d52635e775e0ad9b6439da826a3a (diff)
downloadprotobuf-android13-d1-s1-release.tar.gz
Change-Id: Ieaf7d0ab903fa0186f95144b7f34e193a755335d
-rw-r--r--.cargo_vcs_info.json7
-rw-r--r--Android.bp2
-rw-r--r--Cargo.toml13
-rw-r--r--Cargo.toml.orig2
-rw-r--r--METADATA10
-rw-r--r--README.md97
-rw-r--r--TEST_MAPPING6
-rw-r--r--benches/coded_output_stream.rs3
-rw-r--r--out/version.rs6
-rwxr-xr-xregenerate.sh33
-rw-r--r--src/buf_read_iter.rs191
-rw-r--r--src/buf_read_or_reader.rs85
-rw-r--r--src/coded_input_stream.rs84
-rw-r--r--src/coded_output_stream.rs121
-rw-r--r--src/compiler_plugin.rs7
-rw-r--r--src/descriptor.rs2
-rw-r--r--src/descriptorx.rs1
-rw-r--r--src/lazy.rs3
-rw-r--r--src/lazy_v2.rs3
-rw-r--r--src/lib.rs95
-rw-r--r--src/misc.rs71
-rw-r--r--src/plugin.rs2
-rw-r--r--src/reflect/acc/v1.rs11
-rw-r--r--src/reflect/enums.rs3
-rw-r--r--src/reflect/message.rs5
-rw-r--r--src/reflect/mod.rs4
-rw-r--r--src/reflect/optional.rs1
-rw-r--r--src/reflect/repeated.rs1
-rw-r--r--src/reflect/value.rs4
-rw-r--r--src/repeated.rs6
-rw-r--r--src/rt.rs9
-rw-r--r--src/rustproto.rs180
-rw-r--r--src/singular.rs22
-rw-r--r--src/text_format/lexer/str_lit.rs5
-rw-r--r--src/text_format/mod.rs7
-rw-r--r--src/types.rs4
-rw-r--r--src/unknown.rs12
-rw-r--r--src/varint.rs16
-rw-r--r--src/well_known_types/any.rs2
-rw-r--r--src/well_known_types/api.rs2
-rw-r--r--src/well_known_types/duration.rs2
-rw-r--r--src/well_known_types/empty.rs2
-rw-r--r--src/well_known_types/field_mask.rs2
-rw-r--r--src/well_known_types/source_context.rs2
-rw-r--r--src/well_known_types/struct_pb.rs2
-rw-r--r--src/well_known_types/timestamp.rs2
-rw-r--r--src/well_known_types/type_pb.rs2
-rw-r--r--src/well_known_types/wrappers.rs2
48 files changed, 757 insertions, 397 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 051cfa6..ca74a42 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
{
"git": {
- "sha1": "d65abd3c6cee1dacef1448146b488ee168492a7d"
- }
-}
+ "sha1": "ec31ce829473039ac598ca6fdcb245cbd6fa82ba"
+ },
+ "path_in_vcs": "protobuf"
+} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index d7d1318..78e5734 100644
--- a/Android.bp
+++ b/Android.bp
@@ -30,7 +30,7 @@ rust_library {
host_supported: true,
crate_name: "protobuf",
cargo_env_compat: true,
- cargo_pkg_version: "2.25.1",
+ cargo_pkg_version: "2.27.1",
srcs: [
"src/lib.rs",
":copy_protobuf_build_out",
diff --git a/Cargo.toml b/Cargo.toml
index 005d7bf..9e4935f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,19 +12,23 @@
[package]
edition = "2018"
name = "protobuf"
-version = "2.25.1"
+version = "2.27.1"
authors = ["Stepan Koltsov <stepan.koltsov@gmail.com>"]
-description = "Rust implementation of Google protocol buffers\n"
+description = """
+Rust implementation of Google protocol buffers
+"""
homepage = "https://github.com/stepancheg/rust-protobuf/"
documentation = "https://github.com/stepancheg/rust-protobuf/blob/master/README.md"
license = "MIT"
repository = "https://github.com/stepancheg/rust-protobuf/"
+
[package.metadata.docs.rs]
all-features = true
[lib]
doctest = false
bench = false
+
[dependencies.bytes]
version = "1.0"
optional = true
@@ -40,4 +44,7 @@ optional = true
[features]
with-bytes = ["bytes"]
-with-serde = ["serde", "serde_derive"]
+with-serde = [
+ "serde",
+ "serde_derive",
+]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 058e8f1..c1be2f7 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,7 +1,7 @@
[package]
name = "protobuf"
-version = "2.25.1"
+version = "2.27.1"
authors = ["Stepan Koltsov <stepan.koltsov@gmail.com>"]
edition = "2018"
license = "MIT"
diff --git a/METADATA b/METADATA
index 08ae782..2bcb504 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/protobuf/protobuf-2.25.1.crate"
+ value: "https://static.crates.io/crates/protobuf/protobuf-2.27.1.crate"
}
- version: "2.25.1"
+ version: "2.27.1"
license_type: NOTICE
last_upgrade_date {
- year: 2021
- month: 9
- day: 22
+ year: 2022
+ month: 3
+ day: 1
}
}
diff --git a/README.md b/README.md
index c16838b..af32486 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,95 @@
-## How to develop rust-protobuf itself
+<!-- cargo-sync-readme start -->
-`cargo test --all` to build everything.
+# Library to read and write protocol buffers data
-If code generator is changed, code needs to be regenerated, see
-`regenerate.sh`.
+# Version 2 is stable
+
+Currently developed branch of rust-protobuf [is 3](https://docs.rs/protobuf/%3E=3.0.0-alpha).
+It has the same spirit as version 2, but contains numerous improvements like:
+* runtime reflection for mutability, not just for access
+* protobuf text format and JSON parsing (which rely on reflection)
+* dynamic message support: work with protobuf data without generating code from schema
+
+Stable version of rust-protobuf will be supported until version 3 released.
+
+[Tracking issue for version 3](https://github.com/stepancheg/rust-protobuf/issues/518).
+
+# How to generate rust code
+
+There are several ways to generate rust code from `.proto` files
+
+## Invoke `protoc` programmatically with protoc-rust crate (recommended)
+
+Have a look at readme in [protoc-rust crate](https://docs.rs/protoc-rust/=2).
+
+## Use pure rust protobuf parser and code generator
+
+Readme should be in
+[protobuf-codegen-pure crate](https://docs.rs/protobuf-codegen-pure/=2).
+
+## Use protoc-gen-rust plugin
+
+Readme is [here](https://docs.rs/protobuf-codegen/=2).
+
+## Generated code
+
+Have a look at generated files (for current development version),
+used internally in rust-protobuf:
+
+* [descriptor.rs](https://github.com/stepancheg/rust-protobuf/blob/master/protobuf/src/descriptor.rs)
+ for [descriptor.proto](https://github.com/stepancheg/rust-protobuf/blob/master/protoc-bin-vendored/include/google/protobuf/descriptor.proto)
+ (that is part of Google protobuf)
+
+# Copy on write
+
+Rust-protobuf can be used with [bytes crate](https://github.com/tokio-rs/bytes).
+
+To enable `Bytes` you need to:
+
+1. Enable `with-bytes` feature in rust-protobuf:
+
+```rust
+[dependencies]
+protobuf = { version = "~2.0", features = ["with-bytes"] }
+```
+
+2. Enable bytes option
+
+with `Customize` when codegen is invoked programmatically:
+
+```rust
+protoc_rust::run(protoc_rust::Args {
+ ...
+ customize: Customize {
+ carllerche_bytes_for_bytes: Some(true),
+ carllerche_bytes_for_string: Some(true),
+ ..Default::default()
+ },
+});
+```
+
+or in `.proto` file:
+
+```rust
+import "rustproto.proto";
+
+option (rustproto.carllerche_bytes_for_bytes_all) = true;
+option (rustproto.carllerche_bytes_for_string_all) = true;
+```
+
+With these options enabled, fields of type `bytes` or `string` are
+generated as `Bytes` or `Chars` respectively. When `CodedInputStream` is constructed
+from `Bytes` object, fields of these types get subslices of original `Bytes` object,
+instead of being allocated on heap.
+
+# Accompanying crates
+
+* [`protoc-rust`](https://docs.rs/protoc-rust/=2)
+ and [`protobuf-codegen-pure`](https://docs.rs/protobuf-codegen-pure/=2)
+ can be used to rust code from `.proto` crates.
+* [`protobuf-codegen`](https://docs.rs/protobuf-codegen/=2) for `protoc-gen-rust` protoc plugin.
+* [`protoc`](https://docs.rs/protoc/=2) crate can be used to invoke `protoc` programmatically.
+* [`protoc-bin-vendored`](https://docs.rs/protoc-bin-vendored/=2) contains `protoc` command
+ packed into the crate.
+
+<!-- cargo-sync-readme end -->
diff --git a/TEST_MAPPING b/TEST_MAPPING
index b7c1df9..8229f22 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -2,6 +2,9 @@
{
"presubmit": [
{
+ "name": "authfs_device_test_src_lib"
+ },
+ {
"name": "microdroid_manager_test"
},
{
@@ -10,6 +13,9 @@
],
"presubmit-rust": [
{
+ "name": "authfs_device_test_src_lib"
+ },
+ {
"name": "microdroid_manager_test"
},
{
diff --git a/benches/coded_output_stream.rs b/benches/coded_output_stream.rs
index 0f57a38..9edf95c 100644
--- a/benches/coded_output_stream.rs
+++ b/benches/coded_output_stream.rs
@@ -5,9 +5,10 @@
extern crate protobuf;
extern crate test;
-use self::test::Bencher;
use protobuf::CodedOutputStream;
+use self::test::Bencher;
+
#[inline]
fn buffer_write_byte(os: &mut CodedOutputStream) {
for i in 0..10 {
diff --git a/out/version.rs b/out/version.rs
index fd20f6c..18bbac5 100644
--- a/out/version.rs
+++ b/out/version.rs
@@ -1,7 +1,7 @@
/// protobuf crate version
-pub const VERSION: &'static str = "2.25.1";
+pub const VERSION: &'static str = "2.27.1";
/// This symbol is used by codegen
#[doc(hidden)]
-pub const VERSION_IDENT: &'static str = "VERSION_2_25_1";
+pub const VERSION_IDENT: &'static str = "VERSION_2_27_1";
/// This symbol can be referenced to assert that proper version of crate is used
-pub const VERSION_2_25_1: () = ();
+pub const VERSION_2_27_1: () = ();
diff --git a/regenerate.sh b/regenerate.sh
index 672106e..0173496 100755
--- a/regenerate.sh
+++ b/regenerate.sh
@@ -1,6 +1,6 @@
#!/bin/sh -ex
-cd $(dirname $0)
+cd "$(dirname "$0")"
die() {
echo "$@" >&2
@@ -9,29 +9,35 @@ die() {
protoc_ver=$(protoc --version)
case "$protoc_ver" in
- "libprotoc 3"*) ;;
- *)
- die "you need to use protobuf 3 to regenerate .rs from .proto"
+"libprotoc 3"*) ;;
+*)
+ die "you need to use protobuf 3 to regenerate .rs from .proto"
;;
esac
cargo build --manifest-path=../protobuf-codegen/Cargo.toml
+cargo build --manifest-path=../protoc-bin-vendored/Cargo.toml --bin protoc-bin-which
-where_am_i=$(cd ..; pwd)
+PROTOC=$(cargo run --manifest-path=../protoc-bin-vendored/Cargo.toml --bin protoc-bin-which)
+
+where_am_i=$(
+ cd ..
+ pwd
+)
rm -rf tmp-generated
mkdir tmp-generated
-case `uname` in
- Linux)
- exe_suffix=""
+case $(uname) in
+Linux)
+ exe_suffix=""
;;
- MSYS_NT*)
- exe_suffix=".exe"
+MSYS_NT*)
+ exe_suffix=".exe"
;;
esac
-protoc \
+"$PROTOC" \
--plugin=protoc-gen-rust="$where_am_i/target/debug/protoc-gen-rust$exe_suffix" \
--rust_out tmp-generated \
--rust_opt 'serde_derive=true inside_protobuf=true' \
@@ -45,13 +51,14 @@ mv tmp-generated/descriptor.rs tmp-generated/plugin.rs tmp-generated/rustproto.r
mv tmp-generated/*.rs src/well_known_types/
(
cd src/well_known_types
- exec > mod.rs
+ exec >mod.rs
echo "// This file is generated. Do not edit"
echo '//! Generated code for "well known types"'
echo "//!"
echo "//! [This document](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf) describes these types."
mod_list() {
+ # shellcheck disable=SC2010
ls | grep -v mod.rs | sed -e 's,\.rs$,,'
}
@@ -59,7 +66,7 @@ mv tmp-generated/*.rs src/well_known_types/
mod_list | sed -e 's,^,mod ,; s,$,;,'
echo
- mod_list | while read mod; do
+ mod_list | while read -r mod; do
echo "pub use self::$mod::*;"
done
)
diff --git a/src/buf_read_iter.rs b/src/buf_read_iter.rs
index 37bc353..ff1fce2 100644
--- a/src/buf_read_iter.rs
+++ b/src/buf_read_iter.rs
@@ -3,6 +3,7 @@ use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;
use std::mem;
+use std::mem::MaybeUninit;
use std::u64;
#[cfg(feature = "bytes")]
@@ -14,8 +15,11 @@ use bytes::Bytes;
#[cfg(feature = "bytes")]
use bytes::BytesMut;
+use crate::buf_read_or_reader::BufReadOrReader;
use crate::coded_input_stream::READ_RAW_BYTES_MAX_ALLOC;
use crate::error::WireError;
+use crate::misc::maybe_uninit_write_slice;
+use crate::misc::vec_spare_capacity_mut;
use crate::ProtobufError;
use crate::ProtobufResult;
@@ -29,8 +33,7 @@ const NO_LIMIT: u64 = u64::MAX;
/// Hold all possible combinations of input source
enum InputSource<'a> {
- BufRead(&'a mut dyn BufRead),
- Read(BufReader<&'a mut dyn Read>),
+ Read(BufReadOrReader<'a>),
Slice(&'a [u8]),
#[cfg(feature = "bytes")]
Bytes(&'a Bytes),
@@ -50,7 +53,7 @@ enum InputSource<'a> {
/// It is important for `CodedInputStream` performance that small reads
/// (e. g. 4 bytes reads) do not involve virtual calls or switches.
/// This is achievable with `BufReadIter`.
-pub struct BufReadIter<'a> {
+pub(crate) struct BufReadIter<'a> {
input_source: InputSource<'a>,
buf: &'a [u8],
pos_within_buf: usize,
@@ -62,22 +65,19 @@ pub struct BufReadIter<'a> {
impl<'a> Drop for BufReadIter<'a> {
fn drop(&mut self) {
match self.input_source {
- InputSource::BufRead(ref mut buf_read) => buf_read.consume(self.pos_within_buf),
- InputSource::Read(_) => {
- // Nothing to flush, because we own BufReader
- }
+ InputSource::Read(ref mut buf_read) => buf_read.consume(self.pos_within_buf),
_ => {}
}
}
}
impl<'ignore> BufReadIter<'ignore> {
- pub fn from_read<'a>(read: &'a mut dyn Read) -> BufReadIter<'a> {
+ pub(crate) fn from_read<'a>(read: &'a mut dyn Read) -> BufReadIter<'a> {
BufReadIter {
- input_source: InputSource::Read(BufReader::with_capacity(
+ input_source: InputSource::Read(BufReadOrReader::BufReader(BufReader::with_capacity(
INPUT_STREAM_BUFFER_SIZE,
read,
- )),
+ ))),
buf: &[],
pos_within_buf: 0,
limit_within_buf: 0,
@@ -86,9 +86,9 @@ impl<'ignore> BufReadIter<'ignore> {
}
}
- pub fn from_buf_read<'a>(buf_read: &'a mut dyn BufRead) -> BufReadIter<'a> {
+ pub(crate) fn from_buf_read<'a>(buf_read: &'a mut dyn BufRead) -> BufReadIter<'a> {
BufReadIter {
- input_source: InputSource::BufRead(buf_read),
+ input_source: InputSource::Read(BufReadOrReader::BufRead(buf_read)),
buf: &[],
pos_within_buf: 0,
limit_within_buf: 0,
@@ -97,7 +97,7 @@ impl<'ignore> BufReadIter<'ignore> {
}
}
- pub fn from_byte_slice<'a>(bytes: &'a [u8]) -> BufReadIter<'a> {
+ pub(crate) fn from_byte_slice<'a>(bytes: &'a [u8]) -> BufReadIter<'a> {
BufReadIter {
input_source: InputSource::Slice(bytes),
buf: bytes,
@@ -109,7 +109,7 @@ impl<'ignore> BufReadIter<'ignore> {
}
#[cfg(feature = "bytes")]
- pub fn from_bytes<'a>(bytes: &'a Bytes) -> BufReadIter<'a> {
+ pub(crate) fn from_bytes<'a>(bytes: &'a Bytes) -> BufReadIter<'a> {
BufReadIter {
input_source: InputSource::Bytes(bytes),
buf: &bytes,
@@ -128,7 +128,7 @@ impl<'ignore> BufReadIter<'ignore> {
}
#[inline(always)]
- pub fn pos(&self) -> u64 {
+ pub(crate) fn pos(&self) -> u64 {
self.pos_of_buf_start + self.pos_within_buf as u64
}
@@ -144,7 +144,7 @@ impl<'ignore> BufReadIter<'ignore> {
self.assertions();
}
- pub fn push_limit(&mut self, limit: u64) -> ProtobufResult<u64> {
+ pub(crate) fn push_limit(&mut self, limit: u64) -> ProtobufResult<u64> {
let new_limit = match self.pos().checked_add(limit) {
Some(new_limit) => new_limit,
None => return Err(ProtobufError::WireError(WireError::Other)),
@@ -162,7 +162,7 @@ impl<'ignore> BufReadIter<'ignore> {
}
#[inline]
- pub fn pop_limit(&mut self, limit: u64) {
+ pub(crate) fn pop_limit(&mut self, limit: u64) {
assert!(limit >= self.limit);
self.limit = limit;
@@ -171,7 +171,7 @@ impl<'ignore> BufReadIter<'ignore> {
}
#[inline]
- pub fn remaining_in_buf(&self) -> &[u8] {
+ pub(crate) fn remaining_in_buf(&self) -> &[u8] {
if USE_UNSAFE_FOR_SPEED {
unsafe {
&self
@@ -184,12 +184,12 @@ impl<'ignore> BufReadIter<'ignore> {
}
#[inline(always)]
- pub fn remaining_in_buf_len(&self) -> usize {
+ pub(crate) fn remaining_in_buf_len(&self) -> usize {
self.limit_within_buf - self.pos_within_buf
}
#[inline(always)]
- pub fn bytes_until_limit(&self) -> u64 {
+ pub(crate) fn bytes_until_limit(&self) -> u64 {
if self.limit == NO_LIMIT {
NO_LIMIT
} else {
@@ -198,7 +198,7 @@ impl<'ignore> BufReadIter<'ignore> {
}
#[inline(always)]
- pub fn eof(&mut self) -> ProtobufResult<bool> {
+ pub(crate) fn eof(&mut self) -> ProtobufResult<bool> {
if self.pos_within_buf == self.limit_within_buf {
Ok(self.fill_buf()?.is_empty())
} else {
@@ -207,7 +207,7 @@ impl<'ignore> BufReadIter<'ignore> {
}
#[inline(always)]
- pub fn read_byte(&mut self) -> ProtobufResult<u8> {
+ pub(crate) fn read_byte(&mut self) -> ProtobufResult<u8> {
if self.pos_within_buf == self.limit_within_buf {
self.do_fill_buf()?;
if self.remaining_in_buf_len() == 0 {
@@ -239,52 +239,8 @@ impl<'ignore> BufReadIter<'ignore> {
Ok(len)
}
- /// Read exact number of bytes into `Vec`.
- ///
- /// `Vec` is cleared in the beginning.
- pub fn read_exact_to_vec(&mut self, count: usize, target: &mut Vec<u8>) -> ProtobufResult<()> {
- // TODO: also do some limits when reading from unlimited source
- if count as u64 > self.bytes_until_limit() {
- return Err(ProtobufError::WireError(WireError::TruncatedMessage));
- }
-
- target.clear();
-
- if count >= READ_RAW_BYTES_MAX_ALLOC && count > target.capacity() {
- // avoid calling `reserve` on buf with very large buffer: could be a malformed message
-
- target.reserve(READ_RAW_BYTES_MAX_ALLOC);
-
- while target.len() < count {
- let need_to_read = count - target.len();
- if need_to_read <= target.len() {
- target.reserve_exact(need_to_read);
- } else {
- target.reserve(1);
- }
-
- let max = cmp::min(target.capacity() - target.len(), need_to_read);
- let read = self.read_to_vec(target, max)?;
- if read == 0 {
- return Err(ProtobufError::WireError(WireError::TruncatedMessage));
- }
- }
- } else {
- target.reserve_exact(count);
-
- unsafe {
- self.read_exact(&mut target.get_unchecked_mut(..count))?;
- target.set_len(count);
- }
- }
-
- debug_assert_eq!(count, target.len());
-
- Ok(())
- }
-
#[cfg(feature = "bytes")]
- pub fn read_exact_bytes(&mut self, len: usize) -> ProtobufResult<Bytes> {
+ pub(crate) fn read_exact_bytes(&mut self, len: usize) -> ProtobufResult<Bytes> {
if let InputSource::Bytes(bytes) = self.input_source {
let end = match self.pos_within_buf.checked_add(len) {
Some(end) => end,
@@ -318,13 +274,13 @@ impl<'ignore> BufReadIter<'ignore> {
}
#[cfg(feature = "bytes")]
- unsafe fn uninit_slice_as_mut_slice(slice: &mut UninitSlice) -> &mut [u8] {
+ unsafe fn uninit_slice_as_mut_slice(slice: &mut UninitSlice) -> &mut [MaybeUninit<u8>] {
use std::slice;
- slice::from_raw_parts_mut(slice.as_mut_ptr(), slice.len())
+ slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut MaybeUninit<u8>, slice.len())
}
/// Returns 0 when EOF or limit reached.
- pub fn read(&mut self, buf: &mut [u8]) -> ProtobufResult<usize> {
+ pub(crate) fn read(&mut self, buf: &mut [u8]) -> ProtobufResult<usize> {
self.fill_buf()?;
let rem = &self.buf[self.pos_within_buf..self.limit_within_buf];
@@ -335,14 +291,7 @@ impl<'ignore> BufReadIter<'ignore> {
Ok(len)
}
- pub fn read_exact(&mut self, buf: &mut [u8]) -> ProtobufResult<()> {
- if self.remaining_in_buf_len() >= buf.len() {
- let buf_len = buf.len();
- buf.copy_from_slice(&self.buf[self.pos_within_buf..self.pos_within_buf + buf_len]);
- self.pos_within_buf += buf_len;
- return Ok(());
- }
-
+ fn read_exact_slow(&mut self, buf: &mut [MaybeUninit<u8>]) -> ProtobufResult<()> {
if self.bytes_until_limit() < buf.len() as u64 {
return Err(ProtobufError::WireError(WireError::UnexpectedEof));
}
@@ -356,11 +305,7 @@ impl<'ignore> BufReadIter<'ignore> {
match self.input_source {
InputSource::Read(ref mut buf_read) => {
buf_read.consume(consume);
- buf_read.read_exact(buf)?;
- }
- InputSource::BufRead(ref mut buf_read) => {
- buf_read.consume(consume);
- buf_read.read_exact(buf)?;
+ buf_read.read_exact_uninit(buf)?;
}
_ => {
return Err(ProtobufError::WireError(WireError::UnexpectedEof));
@@ -374,6 +319,65 @@ impl<'ignore> BufReadIter<'ignore> {
Ok(())
}
+ #[inline]
+ pub(crate) fn read_exact(&mut self, buf: &mut [MaybeUninit<u8>]) -> ProtobufResult<()> {
+ if self.remaining_in_buf_len() >= buf.len() {
+ let buf_len = buf.len();
+ maybe_uninit_write_slice(
+ buf,
+ &self.buf[self.pos_within_buf..self.pos_within_buf + buf_len],
+ );
+ self.pos_within_buf += buf_len;
+ return Ok(());
+ }
+
+ self.read_exact_slow(buf)
+ }
+
+ /// Read exact number of bytes into `Vec`.
+ ///
+ /// `Vec` is cleared in the beginning.
+ pub fn read_exact_to_vec(&mut self, count: usize, target: &mut Vec<u8>) -> ProtobufResult<()> {
+ // TODO: also do some limits when reading from unlimited source
+ if count as u64 > self.bytes_until_limit() {
+ return Err(ProtobufError::WireError(WireError::TruncatedMessage));
+ }
+
+ target.clear();
+
+ if count >= READ_RAW_BYTES_MAX_ALLOC && count > target.capacity() {
+ // avoid calling `reserve` on buf with very large buffer: could be a malformed message
+
+ target.reserve(READ_RAW_BYTES_MAX_ALLOC);
+
+ while target.len() < count {
+ let need_to_read = count - target.len();
+ if need_to_read <= target.len() {
+ target.reserve_exact(need_to_read);
+ } else {
+ target.reserve(1);
+ }
+
+ let max = cmp::min(target.capacity() - target.len(), need_to_read);
+ let read = self.read_to_vec(target, max)?;
+ if read == 0 {
+ return Err(ProtobufError::WireError(WireError::TruncatedMessage));
+ }
+ }
+ } else {
+ target.reserve_exact(count);
+
+ unsafe {
+ self.read_exact(&mut vec_spare_capacity_mut(target)[..count])?;
+ target.set_len(count);
+ }
+ }
+
+ debug_assert_eq!(count, target.len());
+
+ Ok(())
+ }
+
fn do_fill_buf(&mut self) -> ProtobufResult<()> {
debug_assert!(self.pos_within_buf == self.limit_within_buf);
@@ -394,10 +398,6 @@ impl<'ignore> BufReadIter<'ignore> {
buf_read.consume(consume);
self.buf = unsafe { mem::transmute(buf_read.fill_buf()?) };
}
- InputSource::BufRead(ref mut buf_read) => {
- buf_read.consume(consume);
- self.buf = unsafe { mem::transmute(buf_read.fill_buf()?) };
- }
_ => {
return Ok(());
}
@@ -409,7 +409,7 @@ impl<'ignore> BufReadIter<'ignore> {
}
#[inline(always)]
- pub fn fill_buf(&mut self) -> ProtobufResult<&[u8]> {
+ pub(crate) fn fill_buf(&mut self) -> ProtobufResult<&[u8]> {
if self.pos_within_buf == self.limit_within_buf {
self.do_fill_buf()?;
}
@@ -425,7 +425,7 @@ impl<'ignore> BufReadIter<'ignore> {
}
#[inline(always)]
- pub fn consume(&mut self, amt: usize) {
+ pub(crate) fn consume(&mut self, amt: usize) {
assert!(amt <= self.limit_within_buf - self.pos_within_buf);
self.pos_within_buf += amt;
}
@@ -433,9 +433,10 @@ impl<'ignore> BufReadIter<'ignore> {
#[cfg(all(test, feature = "bytes"))]
mod test_bytes {
- use super::*;
use std::io::Write;
+ use super::*;
+
fn make_long_string(len: usize) -> Vec<u8> {
let mut s = Vec::new();
while s.len() < len {
@@ -467,11 +468,12 @@ mod test_bytes {
#[cfg(test)]
mod test {
- use super::*;
use std::io;
use std::io::BufRead;
use std::io::Read;
+ use super::*;
+
#[test]
fn eof_at_limit() {
struct Read5ThenPanic {
@@ -509,7 +511,12 @@ mod test {
let _prev_limit = buf_read_iter.push_limit(5);
buf_read_iter.read_byte().expect("read_byte");
buf_read_iter
- .read_exact(&mut [1, 2, 3, 4])
+ .read_exact(&mut [
+ MaybeUninit::uninit(),
+ MaybeUninit::uninit(),
+ MaybeUninit::uninit(),
+ MaybeUninit::uninit(),
+ ])
.expect("read_exact");
assert!(buf_read_iter.eof().expect("eof"));
}
diff --git a/src/buf_read_or_reader.rs b/src/buf_read_or_reader.rs
new file mode 100644
index 0000000..6a47c76
--- /dev/null
+++ b/src/buf_read_or_reader.rs
@@ -0,0 +1,85 @@
+//! `BufRead` pointer or `BufReader` owned.
+
+use std::cmp;
+use std::io;
+use std::io::BufRead;
+use std::io::BufReader;
+use std::io::Read;
+use std::mem::MaybeUninit;
+
+use crate::misc::maybe_uninit_write_slice;
+
+/// Helper type to simplify `BufReadIter` implementation.
+pub(crate) enum BufReadOrReader<'a> {
+ BufReader(BufReader<&'a mut dyn Read>),
+ BufRead(&'a mut dyn BufRead),
+}
+
+impl<'a> Read for BufReadOrReader<'a> {
+ fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
+ match self {
+ BufReadOrReader::BufReader(r) => r.read(buf),
+ BufReadOrReader::BufRead(r) => r.read(buf),
+ }
+ }
+
+ fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, io::Error> {
+ match self {
+ BufReadOrReader::BufReader(r) => r.read_to_end(buf),
+ BufReadOrReader::BufRead(r) => r.read_to_end(buf),
+ }
+ }
+
+ fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), io::Error> {
+ match self {
+ BufReadOrReader::BufReader(r) => r.read_exact(buf),
+ BufReadOrReader::BufRead(r) => r.read_exact(buf),
+ }
+ }
+}
+
+impl<'a> BufReadOrReader<'a> {
+ /// Similar to `read_exact` but reads into `MaybeUninit`.
+ pub(crate) fn read_exact_uninit(
+ &mut self,
+ buf: &mut [MaybeUninit<u8>],
+ ) -> Result<(), io::Error> {
+ let mut pos = 0;
+ while pos != buf.len() {
+ let fill_buf = match self {
+ BufReadOrReader::BufReader(r) => r.fill_buf()?,
+ BufReadOrReader::BufRead(r) => r.fill_buf()?,
+ };
+ if fill_buf.is_empty() {
+ return Err(io::Error::new(
+ io::ErrorKind::UnexpectedEof,
+ "Unexpected end of file",
+ ));
+ }
+ let consume = cmp::min(fill_buf.len(), buf.len() - pos);
+ maybe_uninit_write_slice(&mut buf[pos..pos + consume], &fill_buf[..consume]);
+ match self {
+ BufReadOrReader::BufReader(r) => r.consume(consume),
+ BufReadOrReader::BufRead(r) => r.consume(consume),
+ }
+ pos += consume;
+ }
+ Ok(())
+ }
+}
+
+impl<'a> BufRead for BufReadOrReader<'a> {
+ fn fill_buf(&mut self) -> Result<&[u8], io::Error> {
+ match self {
+ BufReadOrReader::BufReader(r) => r.fill_buf(),
+ BufReadOrReader::BufRead(r) => r.fill_buf(),
+ }
+ }
+
+ fn consume(&mut self, amt: usize) {
+ match self {
+ BufReadOrReader::BufReader(r) => r.consume(amt),
+ BufReadOrReader::BufRead(r) => r.consume(amt),
+ }
+ }
+}
diff --git a/src/coded_input_stream.rs b/src/coded_input_stream.rs
index 52a13a6..a49563c 100644
--- a/src/coded_input_stream.rs
+++ b/src/coded_input_stream.rs
@@ -6,19 +6,21 @@ use std::io;
use std::io::BufRead;
use std::io::Read;
use std::mem;
+use std::mem::MaybeUninit;
use std::slice;
#[cfg(feature = "bytes")]
-use crate::chars::Chars;
-#[cfg(feature = "bytes")]
use bytes::Bytes;
use crate::buf_read_iter::BufReadIter;
+#[cfg(feature = "bytes")]
+use crate::chars::Chars;
use crate::enums::ProtobufEnum;
use crate::error::ProtobufError;
use crate::error::ProtobufResult;
use crate::error::WireError;
use crate::message::Message;
+use crate::misc::maybe_ununit_array_assume_init;
use crate::unknown::UnknownValue;
use crate::wire_format;
use crate::zigzag::decode_zig_zag_32;
@@ -105,12 +107,21 @@ impl<'a> CodedInputStream<'a> {
}
/// Read bytes into given `buf`.
+ #[inline]
+ fn read_exact_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> ProtobufResult<()> {
+ self.source.read_exact(buf)
+ }
+
+ /// Read bytes into given `buf`.
///
/// Return `0` on EOF.
// TODO: overload with `Read::read`
pub fn read(&mut self, buf: &mut [u8]) -> ProtobufResult<()> {
- self.source.read_exact(buf)?;
- Ok(())
+ // SAFETY: same layout
+ let buf = unsafe {
+ slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut MaybeUninit<u8>, buf.len())
+ };
+ self.read_exact_uninit(buf)
}
/// Read exact number of bytes as `Bytes` object.
@@ -248,24 +259,20 @@ impl<'a> CodedInputStream<'a> {
/// Read little-endian 32-bit integer
pub fn read_raw_little_endian32(&mut self) -> ProtobufResult<u32> {
- let mut r = 0u32;
- let bytes: &mut [u8] = unsafe {
- let p: *mut u8 = mem::transmute(&mut r);
- slice::from_raw_parts_mut(p, mem::size_of::<u32>())
- };
- self.read(bytes)?;
- Ok(r.to_le())
+ let mut bytes = [MaybeUninit::uninit(); 4];
+ self.read_exact_uninit(&mut bytes)?;
+ // SAFETY: `read_exact` guarantees that the buffer is filled.
+ let bytes = unsafe { maybe_ununit_array_assume_init(bytes) };
+ Ok(u32::from_le_bytes(bytes))
}
/// Read little-endian 64-bit integer
pub fn read_raw_little_endian64(&mut self) -> ProtobufResult<u64> {
- let mut r = 0u64;
- let bytes: &mut [u8] = unsafe {
- let p: *mut u8 = mem::transmute(&mut r);
- slice::from_raw_parts_mut(p, mem::size_of::<u64>())
- };
- self.read(bytes)?;
- Ok(r.to_le())
+ let mut bytes = [MaybeUninit::uninit(); 8];
+ self.read_exact_uninit(&mut bytes)?;
+ // SAFETY: `read_exact` guarantees that the buffer is filled.
+ let bytes = unsafe { maybe_ununit_array_assume_init(bytes) };
+ Ok(u64::from_le_bytes(bytes))
}
/// Read tag
@@ -596,41 +603,7 @@ impl<'a> CodedInputStream<'a> {
/// Read raw bytes into the supplied vector. The vector will be resized as needed and
/// overwritten.
pub fn read_raw_bytes_into(&mut self, count: u32, target: &mut Vec<u8>) -> ProtobufResult<()> {
- if false {
- // Master uses this version, but keep existing version for a while
- // to avoid possible breakages.
- return self.source.read_exact_to_vec(count as usize, target);
- }
-
- let count = count as usize;
-
- // TODO: also do some limits when reading from unlimited source
- if count as u64 > self.source.bytes_until_limit() {
- return Err(ProtobufError::WireError(WireError::TruncatedMessage));
- }
-
- unsafe {
- target.set_len(0);
- }
-
- if count >= READ_RAW_BYTES_MAX_ALLOC {
- // avoid calling `reserve` on buf with very large buffer: could be a malformed message
-
- let mut take = self.by_ref().take(count as u64);
- take.read_to_end(target)?;
-
- if target.len() != count {
- return Err(ProtobufError::WireError(WireError::TruncatedMessage));
- }
- } else {
- target.reserve(count);
- unsafe {
- target.set_len(count);
- }
-
- self.source.read_exact(target)?;
- }
- Ok(())
+ self.source.read_exact_to_vec(count as usize, target)
}
/// Read exact number of bytes
@@ -795,13 +768,12 @@ mod test {
use std::io::BufRead;
use std::io::Read;
+ use super::CodedInputStream;
+ use super::READ_RAW_BYTES_MAX_ALLOC;
use crate::error::ProtobufError;
use crate::error::ProtobufResult;
use crate::hex::decode_hex;
- use super::CodedInputStream;
- use super::READ_RAW_BYTES_MAX_ALLOC;
-
fn test_read_partial<F>(hex: &str, mut callback: F)
where
F: FnMut(&mut CodedInputStream),
diff --git a/src/coded_output_stream.rs b/src/coded_output_stream.rs
index bbfe228..2bbe0a3 100644
--- a/src/coded_output_stream.rs
+++ b/src/coded_output_stream.rs
@@ -1,17 +1,23 @@
-use crate::misc::remaining_capacity_as_slice_mut;
-use crate::misc::remove_lifetime_mut;
+use std::io;
+use std::io::Write;
+use std::mem;
+use std::mem::MaybeUninit;
+use std::ptr;
+use std::slice;
+
+use crate::misc::maybe_uninit_write;
+use crate::misc::maybe_uninit_write_slice;
+use crate::misc::vec_spare_capacity_mut;
use crate::varint;
use crate::wire_format;
use crate::zigzag::encode_zig_zag_32;
use crate::zigzag::encode_zig_zag_64;
use crate::Message;
use crate::ProtobufEnum;
+use crate::ProtobufError;
use crate::ProtobufResult;
use crate::UnknownFields;
use crate::UnknownValueRef;
-use std::io;
-use std::io::Write;
-use std::mem;
/// Equal to the default buffer size of `BufWriter`, so when
/// `CodedOutputStream` wraps `BufWriter`, it often skips double buffering.
@@ -58,17 +64,27 @@ where
Ok(v)
}
+/// Output buffer/writer for `CodedOutputStream`.
enum OutputTarget<'a> {
Write(&'a mut dyn Write, Vec<u8>),
Vec(&'a mut Vec<u8>),
+ /// The buffer is passed as `&[u8]` to `CodedOutputStream` constructor
+ /// and immediately converted to `buffer` field of `CodedOutputStream`,
+ /// it is not needed to be stored here.
+ /// Lifetime parameter of `CodedOutputStream` guarantees the buffer is valid
+ /// during the lifetime of `CodedOutputStream`.
Bytes,
}
/// Buffered write with handy utilities
pub struct CodedOutputStream<'a> {
target: OutputTarget<'a>,
- // alias to buf from target
- buffer: &'a mut [u8],
+ // Actual buffer is owned by `OutputTarget`,
+ // and here we alias the buffer so access to the buffer is branchless:
+ // access does not require switch by actual target type: `&[], `Vec`, `Write` etc.
+ // We don't access the actual buffer in `OutputTarget` except when
+ // we initialize `buffer` field here.
+ buffer: *mut [MaybeUninit<u8>],
// within buffer
position: usize,
}
@@ -81,15 +97,16 @@ impl<'a> CodedOutputStream<'a> {
let buffer_len = OUTPUT_STREAM_BUFFER_SIZE;
let mut buffer_storage = Vec::with_capacity(buffer_len);
- unsafe {
- buffer_storage.set_len(buffer_len);
- }
- let buffer = unsafe { remove_lifetime_mut(&mut buffer_storage as &mut [u8]) };
+ // SAFETY: we are not using the `buffer_storage`
+ // except for initializing the `buffer` field.
+ // See `buffer` field documentation.
+ let buffer = vec_spare_capacity_mut(&mut buffer_storage);
+ let buffer: *mut [MaybeUninit<u8>] = buffer;
CodedOutputStream {
target: OutputTarget::Write(writer, buffer_storage),
- buffer: buffer,
+ buffer,
position: 0,
}
}
@@ -98,9 +115,12 @@ impl<'a> CodedOutputStream<'a> {
///
/// Attempt to write more than bytes capacity results in error.
pub fn bytes(bytes: &'a mut [u8]) -> CodedOutputStream<'a> {
+ // SAFETY: it is safe to cast from &mut [u8] to &mut [MaybeUninit<u8>].
+ let buffer =
+ ptr::slice_from_raw_parts_mut(bytes.as_mut_ptr() as *mut MaybeUninit<u8>, bytes.len());
CodedOutputStream {
target: OutputTarget::Bytes,
- buffer: bytes,
+ buffer,
position: 0,
}
}
@@ -110,9 +130,10 @@ impl<'a> CodedOutputStream<'a> {
/// Caller should call `flush` at the end to guarantee vec contains
/// all written data.
pub fn vec(vec: &'a mut Vec<u8>) -> CodedOutputStream<'a> {
+ let buffer: *mut [MaybeUninit<u8>] = &mut [];
CodedOutputStream {
target: OutputTarget::Vec(vec),
- buffer: &mut [],
+ buffer,
position: 0,
}
}
@@ -125,7 +146,7 @@ impl<'a> CodedOutputStream<'a> {
pub fn check_eof(&self) {
match self.target {
OutputTarget::Bytes => {
- assert_eq!(self.buffer.len() as u64, self.position as u64);
+ assert_eq!(self.buffer().len() as u64, self.position as u64);
}
OutputTarget::Write(..) | OutputTarget::Vec(..) => {
panic!("must not be called with Writer or Vec");
@@ -133,10 +154,25 @@ impl<'a> CodedOutputStream<'a> {
}
}
+ #[inline(always)]
+ fn buffer(&self) -> &[MaybeUninit<u8>] {
+ // SAFETY: see the `buffer` field documentation about invariants.
+ unsafe { &*(self.buffer as *mut [MaybeUninit<u8>]) }
+ }
+
+ #[inline(always)]
+ fn filled_buffer_impl<'s>(buffer: *mut [MaybeUninit<u8>], position: usize) -> &'s [u8] {
+ // SAFETY: this function is safe assuming `buffer` and `position`
+ // are `self.buffer` and `safe.position`:
+ // * `CodedOutputStream` has invariant that `position <= buffer.len()`.
+ // * `buffer` is filled up to `position`.
+ unsafe { slice::from_raw_parts_mut(buffer as *mut u8, position) }
+ }
+
fn refresh_buffer(&mut self) -> ProtobufResult<()> {
match self.target {
OutputTarget::Write(ref mut write, _) => {
- write.write_all(&self.buffer[0..self.position as usize])?;
+ write.write_all(Self::filled_buffer_impl(self.buffer, self.position))?;
self.position = 0;
}
OutputTarget::Vec(ref mut vec) => unsafe {
@@ -144,11 +180,14 @@ impl<'a> CodedOutputStream<'a> {
assert!(vec_len + self.position <= vec.capacity());
vec.set_len(vec_len + self.position);
vec.reserve(1);
- self.buffer = remove_lifetime_mut(remaining_capacity_as_slice_mut(vec));
+ self.buffer = vec_spare_capacity_mut(vec);
self.position = 0;
},
OutputTarget::Bytes => {
- panic!("refresh_buffer must not be called on CodedOutputStream create from slice");
+ return Err(ProtobufError::IoError(io::Error::new(
+ io::ErrorKind::Other,
+ "given slice is too small to serialize the message",
+ )));
}
}
Ok(())
@@ -167,20 +206,22 @@ impl<'a> CodedOutputStream<'a> {
/// Write a byte
pub fn write_raw_byte(&mut self, byte: u8) -> ProtobufResult<()> {
- if self.position as usize == self.buffer.len() {
+ if self.position as usize == self.buffer().len() {
self.refresh_buffer()?;
}
- self.buffer[self.position as usize] = byte;
+ unsafe { maybe_uninit_write(&mut (&mut *self.buffer)[self.position as usize], byte) };
self.position += 1;
Ok(())
}
/// Write bytes
pub fn write_raw_bytes(&mut self, bytes: &[u8]) -> ProtobufResult<()> {
- if bytes.len() <= self.buffer.len() - self.position {
+ if bytes.len() <= self.buffer().len() - self.position {
let bottom = self.position as usize;
let top = bottom + (bytes.len() as usize);
- self.buffer[bottom..top].copy_from_slice(bytes);
+ // SAFETY: see the `buffer` field documentation about invariants.
+ let buffer = unsafe { &mut (&mut *self.buffer)[bottom..top] };
+ maybe_uninit_write_slice(buffer, bytes);
self.position += bytes.len();
return Ok(());
}
@@ -189,8 +230,11 @@ impl<'a> CodedOutputStream<'a> {
assert!(self.position == 0);
- if self.position + bytes.len() < self.buffer.len() {
- self.buffer[self.position..self.position + bytes.len()].copy_from_slice(bytes);
+ if self.position + bytes.len() < self.buffer().len() {
+ // SAFETY: see the `buffer` field documentation about invariants.
+ let buffer =
+ unsafe { &mut (&mut *self.buffer)[self.position..self.position + bytes.len()] };
+ maybe_uninit_write_slice(buffer, bytes);
self.position += bytes.len();
return Ok(());
}
@@ -204,9 +248,7 @@ impl<'a> CodedOutputStream<'a> {
}
OutputTarget::Vec(ref mut vec) => {
vec.extend(bytes);
- unsafe {
- self.buffer = remove_lifetime_mut(remaining_capacity_as_slice_mut(vec));
- }
+ self.buffer = vec_spare_capacity_mut(vec)
}
}
Ok(())
@@ -223,30 +265,38 @@ impl<'a> CodedOutputStream<'a> {
/// Write varint
pub fn write_raw_varint32(&mut self, value: u32) -> ProtobufResult<()> {
- if self.buffer.len() - self.position >= 5 {
+ if self.buffer().len() - self.position >= 5 {
// fast path
- let len = varint::encode_varint32(value, &mut self.buffer[self.position..]);
+ let len = unsafe {
+ varint::encode_varint32(value, &mut (&mut *self.buffer)[self.position..])
+ };
self.position += len;
Ok(())
} else {
// slow path
let buf = &mut [0u8; 5];
- let len = varint::encode_varint32(value, buf);
+ let len = varint::encode_varint32(value, unsafe {
+ slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut MaybeUninit<u8>, buf.len())
+ });
self.write_raw_bytes(&buf[..len])
}
}
/// Write varint
pub fn write_raw_varint64(&mut self, value: u64) -> ProtobufResult<()> {
- if self.buffer.len() - self.position >= 10 {
+ if self.buffer().len() - self.position >= 10 {
// fast path
- let len = varint::encode_varint64(value, &mut self.buffer[self.position..]);
+ let len = unsafe {
+ varint::encode_varint64(value, &mut (&mut *self.buffer)[self.position..])
+ };
self.position += len;
Ok(())
} else {
// slow path
let buf = &mut [0u8; 10];
- let len = varint::encode_varint64(value, buf);
+ let len = varint::encode_varint64(value, unsafe {
+ slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut MaybeUninit<u8>, buf.len())
+ });
self.write_raw_bytes(&buf[..len])
}
}
@@ -532,13 +582,14 @@ impl<'a> Write for CodedOutputStream<'a> {
#[cfg(test)]
mod test {
+ use std::io::Write;
+ use std::iter;
+
use crate::coded_output_stream::CodedOutputStream;
use crate::hex::decode_hex;
use crate::hex::encode_hex;
use crate::wire_format;
use crate::ProtobufResult;
- use std::io::Write;
- use std::iter;
fn test_write<F>(expected: &str, mut gen: F)
where
diff --git a/src/compiler_plugin.rs b/src/compiler_plugin.rs
index e056071..122eeb3 100644
--- a/src/compiler_plugin.rs
+++ b/src/compiler_plugin.rs
@@ -1,13 +1,14 @@
// TODO: move into separate crate
#![doc(hidden)]
-use crate::descriptor::FileDescriptorProto;
-use crate::plugin::*;
-use crate::Message;
use std::io::stdin;
use std::io::stdout;
use std::str;
+use crate::descriptor::FileDescriptorProto;
+use crate::plugin::*;
+use crate::Message;
+
pub struct GenRequest<'a> {
pub file_descriptors: &'a [FileDescriptorProto],
pub files_to_generate: &'a [String],
diff --git a/src/descriptor.rs b/src/descriptor.rs
index 8f3dd2f..7ca155d 100644
--- a/src/descriptor.rs
+++ b/src/descriptor.rs
@@ -1,4 +1,4 @@
-// This file is generated by rust-protobuf 2.22.0. Do not edit
+// This file is generated by rust-protobuf 2.26.0. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
diff --git a/src/descriptorx.rs b/src/descriptorx.rs
index 82baab8..7b046ec 100644
--- a/src/descriptorx.rs
+++ b/src/descriptorx.rs
@@ -8,7 +8,6 @@ use crate::descriptor::FieldDescriptorProto;
/// utilities to work with descriptor
use crate::descriptor::FileDescriptorProto;
use crate::descriptor::OneofDescriptorProto;
-
use crate::rust;
use crate::strx;
diff --git a/src/lazy.rs b/src/lazy.rs
index 5b01502..3575dd0 100644
--- a/src/lazy.rs
+++ b/src/lazy.rs
@@ -56,13 +56,14 @@ pub const ONCE_INIT: sync::Once = sync::Once::new();
#[cfg(test)]
mod test {
- use super::Lazy;
use std::sync::atomic::AtomicIsize;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::sync::Barrier;
use std::thread;
+ use super::Lazy;
+
#[test]
fn many_threads_calling_get() {
const N_THREADS: usize = 32;
diff --git a/src/lazy_v2.rs b/src/lazy_v2.rs
index 4ba10a5..6f9ac1e 100644
--- a/src/lazy_v2.rs
+++ b/src/lazy_v2.rs
@@ -33,13 +33,14 @@ impl<T: Sync> LazyV2<T> {
#[cfg(test)]
mod test {
- use super::LazyV2;
use std::sync::atomic::AtomicIsize;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::sync::Barrier;
use std::thread;
+ use super::LazyV2;
+
#[test]
fn many_threads_calling_get() {
const N_THREADS: usize = 32;
diff --git a/src/lib.rs b/src/lib.rs
index 8eee9d3..d88e029 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,97 @@
-//! Library to read and write protocol buffers data.
+//! # Library to read and write protocol buffers data
+//!
+//! # Version 2 is stable
+//!
+//! Currently developed branch of rust-protobuf [is 3](https://docs.rs/protobuf/%3E=3.0.0-alpha).
+//! It has the same spirit as version 2, but contains numerous improvements like:
+//! * runtime reflection for mutability, not just for access
+//! * protobuf text format and JSON parsing (which rely on reflection)
+//! * dynamic message support: work with protobuf data without generating code from schema
+//!
+//! Stable version of rust-protobuf will be supported until version 3 released.
+//!
+//! [Tracking issue for version 3](https://github.com/stepancheg/rust-protobuf/issues/518).
+//!
+//! # How to generate rust code
+//!
+//! There are several ways to generate rust code from `.proto` files
+//!
+//! ## Invoke `protoc` programmatically with protoc-rust crate (recommended)
+//!
+//! Have a look at readme in [protoc-rust crate](https://docs.rs/protoc-rust/=2).
+//!
+//! ## Use pure rust protobuf parser and code generator
+//!
+//! Readme should be in
+//! [protobuf-codegen-pure crate](https://docs.rs/protobuf-codegen-pure/=2).
+//!
+//! ## Use protoc-gen-rust plugin
+//!
+//! Readme is [here](https://docs.rs/protobuf-codegen/=2).
+//!
+//! ## Generated code
+//!
+//! Have a look at generated files (for current development version),
+//! used internally in rust-protobuf:
+//!
+//! * [descriptor.rs](https://github.com/stepancheg/rust-protobuf/blob/master/protobuf/src/descriptor.rs)
+//! for [descriptor.proto](https://github.com/stepancheg/rust-protobuf/blob/master/protoc-bin-vendored/include/google/protobuf/descriptor.proto)
+//! (that is part of Google protobuf)
+//!
+//! # Copy on write
+//!
+//! Rust-protobuf can be used with [bytes crate](https://github.com/tokio-rs/bytes).
+//!
+//! To enable `Bytes` you need to:
+//!
+//! 1. Enable `with-bytes` feature in rust-protobuf:
+//!
+//! ```
+//! [dependencies]
+//! protobuf = { version = "~2.0", features = ["with-bytes"] }
+//! ```
+//!
+//! 2. Enable bytes option
+//!
+//! with `Customize` when codegen is invoked programmatically:
+//!
+//! ```ignore
+//! protoc_rust::run(protoc_rust::Args {
+//! ...
+//! customize: Customize {
+//! carllerche_bytes_for_bytes: Some(true),
+//! carllerche_bytes_for_string: Some(true),
+//! ..Default::default()
+//! },
+//! });
+//! ```
+//!
+//! or in `.proto` file:
+//!
+//! ```ignore
+//! import "rustproto.proto";
+//!
+//! option (rustproto.carllerche_bytes_for_bytes_all) = true;
+//! option (rustproto.carllerche_bytes_for_string_all) = true;
+//! ```
+//!
+//! With these options enabled, fields of type `bytes` or `string` are
+//! generated as `Bytes` or `Chars` respectively. When `CodedInputStream` is constructed
+//! from `Bytes` object, fields of these types get subslices of original `Bytes` object,
+//! instead of being allocated on heap.
+//!
+//! # Accompanying crates
+//!
+//! * [`protoc-rust`](https://docs.rs/protoc-rust/=2)
+//! and [`protobuf-codegen-pure`](https://docs.rs/protobuf-codegen-pure/=2)
+//! can be used to rust code from `.proto` crates.
+//! * [`protobuf-codegen`](https://docs.rs/protobuf-codegen/=2) for `protoc-gen-rust` protoc plugin.
+//! * [`protoc`](https://docs.rs/protoc/=2) crate can be used to invoke `protoc` programmatically.
+//! * [`protoc-bin-vendored`](https://docs.rs/protoc-bin-vendored/=2) contains `protoc` command
+//! packed into the crate.
#![deny(missing_docs)]
-#![deny(broken_intra_doc_links)]
+#![deny(rustdoc::broken_intra_doc_links)]
#[cfg(feature = "bytes")]
extern crate bytes;
@@ -90,6 +180,7 @@ mod zigzag;
mod misc;
mod buf_read_iter;
+mod buf_read_or_reader;
/// This symbol is in generated `version.rs`, include here for IDE
#[cfg(never)]
diff --git a/src/misc.rs b/src/misc.rs
index d923d58..faef34f 100644
--- a/src/misc.rs
+++ b/src/misc.rs
@@ -1,37 +1,52 @@
use std::mem;
+use std::mem::MaybeUninit;
use std::slice;
-/// Slice from `vec[vec.len()..vec.capacity()]`
-pub unsafe fn remaining_capacity_as_slice_mut<A>(vec: &mut Vec<A>) -> &mut [A] {
- slice::from_raw_parts_mut(
- vec.as_mut_slice().as_mut_ptr().offset(vec.len() as isize),
- vec.capacity() - vec.len(),
- )
+/// `Vec::spare_capacity_mut` is not stable until Rust 1.60.
+pub(crate) fn vec_spare_capacity_mut<A>(vec: &mut Vec<A>) -> &mut [MaybeUninit<A>] {
+ // SAFETY: copy-paste from rust stdlib.
+ unsafe {
+ slice::from_raw_parts_mut(
+ vec.as_mut_ptr().add(vec.len()) as *mut MaybeUninit<A>,
+ vec.capacity() - vec.len(),
+ )
+ }
}
-pub unsafe fn remove_lifetime_mut<A: ?Sized>(a: &mut A) -> &'static mut A {
- mem::transmute(a)
+/// `MaybeUninit::write_slice` is not stable.
+pub(crate) fn maybe_uninit_write_slice<'a, T>(
+ this: &'a mut [MaybeUninit<T>],
+ src: &[T],
+) -> &'a mut [T]
+where
+ T: Copy,
+{
+ // SAFETY: copy-paste from rust stdlib.
+
+ let uninit_src: &[MaybeUninit<T>] = unsafe { mem::transmute(src) };
+
+ this.copy_from_slice(uninit_src);
+
+ unsafe { &mut *(this as *mut [MaybeUninit<T>] as *mut [T]) }
}
-#[cfg(test)]
-mod test {
- use super::*;
+/// `MaybeUninit::array_assume_init` is not stable.
+#[inline]
+pub(crate) unsafe fn maybe_ununit_array_assume_init<T, const N: usize>(
+ array: [MaybeUninit<T>; N],
+) -> [T; N] {
+ // SAFETY:
+ // * The caller guarantees that all elements of the array are initialized
+ // * `MaybeUninit<T>` and T are guaranteed to have the same layout
+ // * `MaybeUninit` does not drop, so there are no double-frees
+ // And thus the conversion is safe
+ (&array as *const _ as *const [T; N]).read()
+}
- #[test]
- fn test_remaining_capacity_as_slice_mut() {
- let mut v = Vec::with_capacity(5);
- v.push(10);
- v.push(11);
- v.push(12);
- unsafe {
- {
- let s = remaining_capacity_as_slice_mut(&mut v);
- assert_eq!(2, s.len());
- s[0] = 13;
- s[1] = 14;
- }
- v.set_len(5);
- }
- assert_eq!(vec![10, 11, 12, 13, 14], v);
- }
+/// `MaybeUninit::write` is stable since 1.55.
+#[inline]
+pub(crate) fn maybe_uninit_write<T>(uninit: &mut MaybeUninit<T>, val: T) -> &mut T {
+ // SAFETY: copy-paste from rust stdlib.
+ *uninit = MaybeUninit::new(val);
+ unsafe { &mut *uninit.as_mut_ptr() }
}
diff --git a/src/plugin.rs b/src/plugin.rs
index 77e1666..93f2ca8 100644
--- a/src/plugin.rs
+++ b/src/plugin.rs
@@ -1,4 +1,4 @@
-// This file is generated by rust-protobuf 2.22.0. Do not edit
+// This file is generated by rust-protobuf 2.26.0. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
diff --git a/src/reflect/acc/v1.rs b/src/reflect/acc/v1.rs
index d6bd3d3..4c55f8f 100644
--- a/src/reflect/acc/v1.rs
+++ b/src/reflect/acc/v1.rs
@@ -9,21 +9,20 @@ use std::hash::Hash;
use crate::enums::ProtobufEnum;
use crate::message::message_down_cast;
use crate::message::Message;
-use crate::reflect::EnumValueDescriptor;
-use crate::reflect::ProtobufValue;
-use crate::reflect::ReflectFieldRef;
-use crate::reflect::ReflectValueRef;
-use crate::types::*;
-
use crate::reflect::map::ReflectMap;
use crate::reflect::optional::ReflectOptional;
use crate::reflect::repeated::ReflectRepeated;
use crate::reflect::repeated::ReflectRepeatedEnum;
use crate::reflect::repeated::ReflectRepeatedMessage;
use crate::reflect::rt::FieldAccessor;
+use crate::reflect::EnumValueDescriptor;
+use crate::reflect::ProtobufValue;
+use crate::reflect::ReflectFieldRef;
+use crate::reflect::ReflectValueRef;
use crate::repeated::RepeatedField;
use crate::singular::SingularField;
use crate::singular::SingularPtrField;
+use crate::types::*;
/// this trait should not be used directly, use `FieldDescriptor` instead
pub trait FieldAccessorTrait: Sync + 'static {
diff --git a/src/reflect/enums.rs b/src/reflect/enums.rs
index f1ad901..a25be6f 100644
--- a/src/reflect/enums.rs
+++ b/src/reflect/enums.rs
@@ -1,3 +1,5 @@
+use std::collections::HashMap;
+
use crate::descriptor::EnumDescriptorProto;
use crate::descriptor::EnumValueDescriptorProto;
use crate::descriptor::FileDescriptorProto;
@@ -5,7 +7,6 @@ use crate::descriptorx::find_enum_by_rust_name;
use crate::reflect::find_message_or_enum::find_message_or_enum;
use crate::reflect::find_message_or_enum::MessageOrEnum;
use crate::ProtobufEnum;
-use std::collections::HashMap;
/// Description for enum variant.
///
diff --git a/src/reflect/message.rs b/src/reflect/message.rs
index 53ea2ce..0db9821 100644
--- a/src/reflect/message.rs
+++ b/src/reflect/message.rs
@@ -1,3 +1,6 @@
+use std::collections::HashMap;
+use std::marker;
+
use crate::descriptor::DescriptorProto;
use crate::descriptor::FileDescriptorProto;
use crate::descriptorx::find_message_by_rust_name;
@@ -6,8 +9,6 @@ use crate::reflect::find_message_or_enum::find_message_or_enum;
use crate::reflect::find_message_or_enum::MessageOrEnum;
use crate::reflect::FieldDescriptor;
use crate::Message;
-use std::collections::HashMap;
-use std::marker;
trait MessageFactory: Send + Sync + 'static {
fn new_instance(&self) -> Box<dyn Message>;
diff --git a/src/reflect/mod.rs b/src/reflect/mod.rs
index 392f629..e120e16 100644
--- a/src/reflect/mod.rs
+++ b/src/reflect/mod.rs
@@ -23,8 +23,6 @@ pub mod rt;
pub use self::enums::EnumDescriptor;
pub use self::enums::EnumValueDescriptor;
-
-pub use self::message::MessageDescriptor;
-
pub use self::field::FieldDescriptor;
pub use self::field::ReflectFieldRef;
+pub use self::message::MessageDescriptor;
diff --git a/src/reflect/optional.rs b/src/reflect/optional.rs
index f81f973..f719a2c 100644
--- a/src/reflect/optional.rs
+++ b/src/reflect/optional.rs
@@ -1,7 +1,6 @@
use std::mem;
use super::value::ProtobufValue;
-
use crate::singular::*;
pub trait ReflectOptional: 'static {
diff --git a/src/reflect/repeated.rs b/src/reflect/repeated.rs
index be232f4..710de3e 100644
--- a/src/reflect/repeated.rs
+++ b/src/reflect/repeated.rs
@@ -2,7 +2,6 @@ use std::slice;
use super::value::ProtobufValue;
use super::value::ReflectValueRef;
-
use crate::repeated::RepeatedField;
pub trait ReflectRepeated: 'static {
diff --git a/src/reflect/value.rs b/src/reflect/value.rs
index 16d5266..9598b9f 100644
--- a/src/reflect/value.rs
+++ b/src/reflect/value.rs
@@ -1,11 +1,11 @@
use std::any::Any;
#[cfg(feature = "bytes")]
-use crate::chars::Chars;
-#[cfg(feature = "bytes")]
use bytes::Bytes;
use super::*;
+#[cfg(feature = "bytes")]
+use crate::chars::Chars;
/// Type implemented by all protobuf elementary types
/// (ints, floats, bool, string, bytes, enums, messages).
diff --git a/src/repeated.rs b/src/repeated.rs
index d157f0c..0b749d9 100644
--- a/src/repeated.rs
+++ b/src/repeated.rs
@@ -1,6 +1,3 @@
-#[cfg(feature = "with-serde")]
-use serde;
-
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::default::Default;
@@ -16,6 +13,9 @@ use std::ops::IndexMut;
use std::slice;
use std::vec;
+#[cfg(feature = "with-serde")]
+use serde;
+
use crate::clear::Clear;
/// Wrapper around vector to avoid deallocations on clear.
diff --git a/src/rt.rs b/src/rt.rs
index 3bb0280..fca1254 100644
--- a/src/rt.rs
+++ b/src/rt.rs
@@ -6,27 +6,26 @@ use std::default::Default;
use std::hash::Hash;
#[cfg(feature = "bytes")]
-use crate::chars::Chars;
-#[cfg(feature = "bytes")]
use bytes::Bytes;
+#[cfg(feature = "bytes")]
+use crate::chars::Chars;
use crate::coded_input_stream::CodedInputStream;
use crate::coded_output_stream::CodedOutputStream;
use crate::enums::ProtobufEnum;
use crate::error::ProtobufError;
use crate::error::ProtobufResult;
use crate::error::WireError;
+pub use crate::lazy_v2::LazyV2;
use crate::message::*;
use crate::repeated::RepeatedField;
use crate::singular::SingularField;
use crate::singular::SingularPtrField;
use crate::types::*;
-use crate::zigzag::*;
-
-pub use crate::lazy_v2::LazyV2;
use crate::unknown::UnknownFields;
use crate::wire_format;
use crate::wire_format::WireType;
+use crate::zigzag::*;
/// Given `u64` value compute varint encoded length.
pub fn compute_raw_varint64_size(value: u64) -> u32 {
diff --git a/src/rustproto.rs b/src/rustproto.rs
index 83854e4..75df067 100644
--- a/src/rustproto.rs
+++ b/src/rustproto.rs
@@ -1,4 +1,4 @@
-// This file is generated by rust-protobuf 2.22.0. Do not edit
+// This file is generated by rust-protobuf 2.26.0. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
@@ -59,6 +59,8 @@ pub mod exts {
pub const carllerche_bytes_for_bytes_field: crate::ext::ExtFieldOptional<crate::descriptor::FieldOptions, crate::types::ProtobufTypeBool> = crate::ext::ExtFieldOptional { field_number: 17011, phantom: ::std::marker::PhantomData };
pub const carllerche_bytes_for_string_field: crate::ext::ExtFieldOptional<crate::descriptor::FieldOptions, crate::types::ProtobufTypeBool> = crate::ext::ExtFieldOptional { field_number: 17012, phantom: ::std::marker::PhantomData };
+
+ pub const serde_rename_all: crate::ext::ExtFieldOptional<crate::descriptor::EnumOptions, crate::types::ProtobufTypeString> = crate::ext::ExtFieldOptional { field_number: 17032, phantom: ::std::marker::PhantomData };
}
static file_descriptor_proto_data: &'static [u8] = b"\
@@ -94,92 +96,98 @@ static file_descriptor_proto_data: &'static [u8] = b"\
s_for_bytes_field\x18\xf3\x84\x01\x20\x01(\x08\x12\x1d.google.protobuf.F\
ieldOptionsR\x1ccarllercheBytesForBytesField:i\n!carllerche_bytes_for_st\
ring_field\x18\xf4\x84\x01\x20\x01(\x08\x12\x1d.google.protobuf.FieldOpt\
- ionsR\x1dcarllercheBytesForStringFieldJ\xf2\x13\n\x06\x12\x04\0\07\x01\n\
- \x08\n\x01\x0c\x12\x03\0\0\x12\n\t\n\x02\x03\0\x12\x03\x02\0*\nh\n\x01\
- \x02\x12\x03\x07\0\x122^\x20see\x20https://github.com/gogo/protobuf/blob\
- /master/gogoproto/gogo.proto\n\x20for\x20the\x20original\x20idea\n\n\t\n\
- \x01\x07\x12\x04\t\0\x1b\x01\n7\n\x02\x07\0\x12\x03\x0b\x04+\x1a,\x20Whe\
- n\x20true,\x20oneof\x20field\x20is\x20generated\x20public\n\n\n\n\x03\
- \x07\0\x02\x12\x03\t\x07\"\n\n\n\x03\x07\0\x04\x12\x03\x0b\x04\x0c\n\n\n\
- \x03\x07\0\x05\x12\x03\x0b\r\x11\n\n\n\x03\x07\0\x01\x12\x03\x0b\x12\"\n\
- \n\n\x03\x07\0\x03\x12\x03\x0b%*\nI\n\x02\x07\x01\x12\x03\r\x04,\x1a>\
- \x20When\x20true\x20all\x20fields\x20are\x20public,\x20and\x20not\x20acc\
- essors\x20generated\n\n\n\n\x03\x07\x01\x02\x12\x03\t\x07\"\n\n\n\x03\
- \x07\x01\x04\x12\x03\r\x04\x0c\n\n\n\x03\x07\x01\x05\x12\x03\r\r\x11\n\n\
- \n\x03\x07\x01\x01\x12\x03\r\x12#\n\n\n\x03\x07\x01\x03\x12\x03\r&+\nP\n\
- \x02\x07\x02\x12\x03\x0f\x041\x1aE\x20When\x20false,\x20`get_`,\x20`set_\
- `,\x20`mut_`\x20etc.\x20accessors\x20are\x20not\x20generated\n\n\n\n\x03\
- \x07\x02\x02\x12\x03\t\x07\"\n\n\n\x03\x07\x02\x04\x12\x03\x0f\x04\x0c\n\
- \n\n\x03\x07\x02\x05\x12\x03\x0f\r\x11\n\n\n\x03\x07\x02\x01\x12\x03\x0f\
- \x12(\n\n\n\x03\x07\x02\x03\x12\x03\x0f+0\n2\n\x02\x07\x03\x12\x03\x11\
- \x049\x1a'\x20Use\x20`bytes::Bytes`\x20for\x20`bytes`\x20fields\n\n\n\n\
- \x03\x07\x03\x02\x12\x03\t\x07\"\n\n\n\x03\x07\x03\x04\x12\x03\x11\x04\
- \x0c\n\n\n\x03\x07\x03\x05\x12\x03\x11\r\x11\n\n\n\x03\x07\x03\x01\x12\
- \x03\x11\x120\n\n\n\x03\x07\x03\x03\x12\x03\x1138\n3\n\x02\x07\x04\x12\
- \x03\x13\x04:\x1a(\x20Use\x20`bytes::Bytes`\x20for\x20`string`\x20fields\
- \n\n\n\n\x03\x07\x04\x02\x12\x03\t\x07\"\n\n\n\x03\x07\x04\x04\x12\x03\
- \x13\x04\x0c\n\n\n\x03\x07\x04\x05\x12\x03\x13\r\x11\n\n\n\x03\x07\x04\
- \x01\x12\x03\x13\x121\n\n\n\x03\x07\x04\x03\x12\x03\x1349\nJ\n\x02\x07\
- \x05\x12\x03\x15\x04+\x1a?\x20Use\x20`serde_derive`\x20to\x20implement\
- \x20`Serialize`\x20and\x20`Deserialize`\n\n\n\n\x03\x07\x05\x02\x12\x03\
- \t\x07\"\n\n\n\x03\x07\x05\x04\x12\x03\x15\x04\x0c\n\n\n\x03\x07\x05\x05\
- \x12\x03\x15\r\x11\n\n\n\x03\x07\x05\x01\x12\x03\x15\x12\"\n\n\n\x03\x07\
- \x05\x03\x12\x03\x15%*\n3\n\x02\x07\x06\x12\x03\x17\x041\x1a(\x20Guard\
- \x20serde\x20annotations\x20with\x20cfg\x20attr.\n\n\n\n\x03\x07\x06\x02\
- \x12\x03\t\x07\"\n\n\n\x03\x07\x06\x04\x12\x03\x17\x04\x0c\n\n\n\x03\x07\
- \x06\x05\x12\x03\x17\r\x13\n\n\n\x03\x07\x06\x01\x12\x03\x17\x14(\n\n\n\
- \x03\x07\x06\x03\x12\x03\x17+0\nN\n\x02\x07\x07\x12\x03\x1a\x04+\x1aC\
- \x20When\x20true,\x20will\x20only\x20generate\x20codes\x20that\x20works\
- \x20with\x20lite\x20runtime.\n\n\n\n\x03\x07\x07\x02\x12\x03\t\x07\"\n\n\
- \n\x03\x07\x07\x04\x12\x03\x1a\x04\x0c\n\n\n\x03\x07\x07\x05\x12\x03\x1a\
- \r\x11\n\n\n\x03\x07\x07\x01\x12\x03\x1a\x12\"\n\n\n\x03\x07\x07\x03\x12\
- \x03\x1a%*\n\t\n\x01\x07\x12\x04\x1d\0,\x01\n7\n\x02\x07\x08\x12\x03\x1f\
- \x04'\x1a,\x20When\x20true,\x20oneof\x20field\x20is\x20generated\x20publ\
- ic\n\n\n\n\x03\x07\x08\x02\x12\x03\x1d\x07%\n\n\n\x03\x07\x08\x04\x12\
- \x03\x1f\x04\x0c\n\n\n\x03\x07\x08\x05\x12\x03\x1f\r\x11\n\n\n\x03\x07\
- \x08\x01\x12\x03\x1f\x12\x1e\n\n\n\x03\x07\x08\x03\x12\x03\x1f!&\nI\n\
- \x02\x07\t\x12\x03!\x04(\x1a>\x20When\x20true\x20all\x20fields\x20are\
- \x20public,\x20and\x20not\x20accessors\x20generated\n\n\n\n\x03\x07\t\
- \x02\x12\x03\x1d\x07%\n\n\n\x03\x07\t\x04\x12\x03!\x04\x0c\n\n\n\x03\x07\
- \t\x05\x12\x03!\r\x11\n\n\n\x03\x07\t\x01\x12\x03!\x12\x1f\n\n\n\x03\x07\
- \t\x03\x12\x03!\"'\nP\n\x02\x07\n\x12\x03#\x04-\x1aE\x20When\x20false,\
- \x20`get_`,\x20`set_`,\x20`mut_`\x20etc.\x20accessors\x20are\x20not\x20g\
- enerated\n\n\n\n\x03\x07\n\x02\x12\x03\x1d\x07%\n\n\n\x03\x07\n\x04\x12\
- \x03#\x04\x0c\n\n\n\x03\x07\n\x05\x12\x03#\r\x11\n\n\n\x03\x07\n\x01\x12\
- \x03#\x12$\n\n\n\x03\x07\n\x03\x12\x03#',\n2\n\x02\x07\x0b\x12\x03%\x045\
- \x1a'\x20Use\x20`bytes::Bytes`\x20for\x20`bytes`\x20fields\n\n\n\n\x03\
- \x07\x0b\x02\x12\x03\x1d\x07%\n\n\n\x03\x07\x0b\x04\x12\x03%\x04\x0c\n\n\
- \n\x03\x07\x0b\x05\x12\x03%\r\x11\n\n\n\x03\x07\x0b\x01\x12\x03%\x12,\n\
- \n\n\x03\x07\x0b\x03\x12\x03%/4\n3\n\x02\x07\x0c\x12\x03'\x046\x1a(\x20U\
- se\x20`bytes::Bytes`\x20for\x20`string`\x20fields\n\n\n\n\x03\x07\x0c\
- \x02\x12\x03\x1d\x07%\n\n\n\x03\x07\x0c\x04\x12\x03'\x04\x0c\n\n\n\x03\
- \x07\x0c\x05\x12\x03'\r\x11\n\n\n\x03\x07\x0c\x01\x12\x03'\x12-\n\n\n\
- \x03\x07\x0c\x03\x12\x03'05\nJ\n\x02\x07\r\x12\x03)\x04'\x1a?\x20Use\x20\
+ ionsR\x1dcarllercheBytesForStringField:H\n\x10serde_rename_all\x18\x88\
+ \x85\x01\x20\x01(\t\x12\x1c.google.protobuf.EnumOptionsR\x0eserdeRenameA\
+ llJ\xea\x14\n\x06\x12\x04\0\0<\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\t\n\
+ \x02\x03\0\x12\x03\x02\0*\nh\n\x01\x02\x12\x03\x07\0\x122^\x20see\x20htt\
+ ps://github.com/gogo/protobuf/blob/master/gogoproto/gogo.proto\n\x20for\
+ \x20the\x20original\x20idea\n\n\t\n\x01\x07\x12\x04\t\0\x1b\x01\n7\n\x02\
+ \x07\0\x12\x03\x0b\x04+\x1a,\x20When\x20true,\x20oneof\x20field\x20is\
+ \x20generated\x20public\n\n\n\n\x03\x07\0\x02\x12\x03\t\x07\"\n\n\n\x03\
+ \x07\0\x04\x12\x03\x0b\x04\x0c\n\n\n\x03\x07\0\x05\x12\x03\x0b\r\x11\n\n\
+ \n\x03\x07\0\x01\x12\x03\x0b\x12\"\n\n\n\x03\x07\0\x03\x12\x03\x0b%*\nI\
+ \n\x02\x07\x01\x12\x03\r\x04,\x1a>\x20When\x20true\x20all\x20fields\x20a\
+ re\x20public,\x20and\x20not\x20accessors\x20generated\n\n\n\n\x03\x07\
+ \x01\x02\x12\x03\t\x07\"\n\n\n\x03\x07\x01\x04\x12\x03\r\x04\x0c\n\n\n\
+ \x03\x07\x01\x05\x12\x03\r\r\x11\n\n\n\x03\x07\x01\x01\x12\x03\r\x12#\n\
+ \n\n\x03\x07\x01\x03\x12\x03\r&+\nP\n\x02\x07\x02\x12\x03\x0f\x041\x1aE\
+ \x20When\x20false,\x20`get_`,\x20`set_`,\x20`mut_`\x20etc.\x20accessors\
+ \x20are\x20not\x20generated\n\n\n\n\x03\x07\x02\x02\x12\x03\t\x07\"\n\n\
+ \n\x03\x07\x02\x04\x12\x03\x0f\x04\x0c\n\n\n\x03\x07\x02\x05\x12\x03\x0f\
+ \r\x11\n\n\n\x03\x07\x02\x01\x12\x03\x0f\x12(\n\n\n\x03\x07\x02\x03\x12\
+ \x03\x0f+0\n2\n\x02\x07\x03\x12\x03\x11\x049\x1a'\x20Use\x20`bytes::Byte\
+ s`\x20for\x20`bytes`\x20fields\n\n\n\n\x03\x07\x03\x02\x12\x03\t\x07\"\n\
+ \n\n\x03\x07\x03\x04\x12\x03\x11\x04\x0c\n\n\n\x03\x07\x03\x05\x12\x03\
+ \x11\r\x11\n\n\n\x03\x07\x03\x01\x12\x03\x11\x120\n\n\n\x03\x07\x03\x03\
+ \x12\x03\x1138\n3\n\x02\x07\x04\x12\x03\x13\x04:\x1a(\x20Use\x20`bytes::\
+ Bytes`\x20for\x20`string`\x20fields\n\n\n\n\x03\x07\x04\x02\x12\x03\t\
+ \x07\"\n\n\n\x03\x07\x04\x04\x12\x03\x13\x04\x0c\n\n\n\x03\x07\x04\x05\
+ \x12\x03\x13\r\x11\n\n\n\x03\x07\x04\x01\x12\x03\x13\x121\n\n\n\x03\x07\
+ \x04\x03\x12\x03\x1349\nJ\n\x02\x07\x05\x12\x03\x15\x04+\x1a?\x20Use\x20\
`serde_derive`\x20to\x20implement\x20`Serialize`\x20and\x20`Deserialize`\
- \n\n\n\n\x03\x07\r\x02\x12\x03\x1d\x07%\n\n\n\x03\x07\r\x04\x12\x03)\x04\
- \x0c\n\n\n\x03\x07\r\x05\x12\x03)\r\x11\n\n\n\x03\x07\r\x01\x12\x03)\x12\
- \x1e\n\n\n\x03\x07\r\x03\x12\x03)!&\n3\n\x02\x07\x0e\x12\x03+\x04-\x1a(\
- \x20Guard\x20serde\x20annotations\x20with\x20cfg\x20attr.\n\n\n\n\x03\
- \x07\x0e\x02\x12\x03\x1d\x07%\n\n\n\x03\x07\x0e\x04\x12\x03+\x04\x0c\n\n\
- \n\x03\x07\x0e\x05\x12\x03+\r\x13\n\n\n\x03\x07\x0e\x01\x12\x03+\x14$\n\
- \n\n\x03\x07\x0e\x03\x12\x03+',\n\t\n\x01\x07\x12\x04.\07\x01\nI\n\x02\
- \x07\x0f\x12\x030\x04.\x1a>\x20When\x20true\x20all\x20fields\x20are\x20p\
- ublic,\x20and\x20not\x20accessors\x20generated\n\n\n\n\x03\x07\x0f\x02\
- \x12\x03.\x07#\n\n\n\x03\x07\x0f\x04\x12\x030\x04\x0c\n\n\n\x03\x07\x0f\
- \x05\x12\x030\r\x11\n\n\n\x03\x07\x0f\x01\x12\x030\x12%\n\n\n\x03\x07\
- \x0f\x03\x12\x030(-\nP\n\x02\x07\x10\x12\x032\x043\x1aE\x20When\x20false\
- ,\x20`get_`,\x20`set_`,\x20`mut_`\x20etc.\x20accessors\x20are\x20not\x20\
- generated\n\n\n\n\x03\x07\x10\x02\x12\x03.\x07#\n\n\n\x03\x07\x10\x04\
- \x12\x032\x04\x0c\n\n\n\x03\x07\x10\x05\x12\x032\r\x11\n\n\n\x03\x07\x10\
- \x01\x12\x032\x12*\n\n\n\x03\x07\x10\x03\x12\x032-2\n2\n\x02\x07\x11\x12\
- \x034\x04;\x1a'\x20Use\x20`bytes::Bytes`\x20for\x20`bytes`\x20fields\n\n\
- \n\n\x03\x07\x11\x02\x12\x03.\x07#\n\n\n\x03\x07\x11\x04\x12\x034\x04\
- \x0c\n\n\n\x03\x07\x11\x05\x12\x034\r\x11\n\n\n\x03\x07\x11\x01\x12\x034\
- \x122\n\n\n\x03\x07\x11\x03\x12\x0345:\n3\n\x02\x07\x12\x12\x036\x04<\
- \x1a(\x20Use\x20`bytes::Bytes`\x20for\x20`string`\x20fields\n\n\n\n\x03\
- \x07\x12\x02\x12\x03.\x07#\n\n\n\x03\x07\x12\x04\x12\x036\x04\x0c\n\n\n\
- \x03\x07\x12\x05\x12\x036\r\x11\n\n\n\x03\x07\x12\x01\x12\x036\x123\n\n\
- \n\x03\x07\x12\x03\x12\x0366;\
+ \n\n\n\n\x03\x07\x05\x02\x12\x03\t\x07\"\n\n\n\x03\x07\x05\x04\x12\x03\
+ \x15\x04\x0c\n\n\n\x03\x07\x05\x05\x12\x03\x15\r\x11\n\n\n\x03\x07\x05\
+ \x01\x12\x03\x15\x12\"\n\n\n\x03\x07\x05\x03\x12\x03\x15%*\n3\n\x02\x07\
+ \x06\x12\x03\x17\x041\x1a(\x20Guard\x20serde\x20annotations\x20with\x20c\
+ fg\x20attr.\n\n\n\n\x03\x07\x06\x02\x12\x03\t\x07\"\n\n\n\x03\x07\x06\
+ \x04\x12\x03\x17\x04\x0c\n\n\n\x03\x07\x06\x05\x12\x03\x17\r\x13\n\n\n\
+ \x03\x07\x06\x01\x12\x03\x17\x14(\n\n\n\x03\x07\x06\x03\x12\x03\x17+0\nN\
+ \n\x02\x07\x07\x12\x03\x1a\x04+\x1aC\x20When\x20true,\x20will\x20only\
+ \x20generate\x20codes\x20that\x20works\x20with\x20lite\x20runtime.\n\n\n\
+ \n\x03\x07\x07\x02\x12\x03\t\x07\"\n\n\n\x03\x07\x07\x04\x12\x03\x1a\x04\
+ \x0c\n\n\n\x03\x07\x07\x05\x12\x03\x1a\r\x11\n\n\n\x03\x07\x07\x01\x12\
+ \x03\x1a\x12\"\n\n\n\x03\x07\x07\x03\x12\x03\x1a%*\n\t\n\x01\x07\x12\x04\
+ \x1d\0,\x01\n7\n\x02\x07\x08\x12\x03\x1f\x04'\x1a,\x20When\x20true,\x20o\
+ neof\x20field\x20is\x20generated\x20public\n\n\n\n\x03\x07\x08\x02\x12\
+ \x03\x1d\x07%\n\n\n\x03\x07\x08\x04\x12\x03\x1f\x04\x0c\n\n\n\x03\x07\
+ \x08\x05\x12\x03\x1f\r\x11\n\n\n\x03\x07\x08\x01\x12\x03\x1f\x12\x1e\n\n\
+ \n\x03\x07\x08\x03\x12\x03\x1f!&\nI\n\x02\x07\t\x12\x03!\x04(\x1a>\x20Wh\
+ en\x20true\x20all\x20fields\x20are\x20public,\x20and\x20not\x20accessors\
+ \x20generated\n\n\n\n\x03\x07\t\x02\x12\x03\x1d\x07%\n\n\n\x03\x07\t\x04\
+ \x12\x03!\x04\x0c\n\n\n\x03\x07\t\x05\x12\x03!\r\x11\n\n\n\x03\x07\t\x01\
+ \x12\x03!\x12\x1f\n\n\n\x03\x07\t\x03\x12\x03!\"'\nP\n\x02\x07\n\x12\x03\
+ #\x04-\x1aE\x20When\x20false,\x20`get_`,\x20`set_`,\x20`mut_`\x20etc.\
+ \x20accessors\x20are\x20not\x20generated\n\n\n\n\x03\x07\n\x02\x12\x03\
+ \x1d\x07%\n\n\n\x03\x07\n\x04\x12\x03#\x04\x0c\n\n\n\x03\x07\n\x05\x12\
+ \x03#\r\x11\n\n\n\x03\x07\n\x01\x12\x03#\x12$\n\n\n\x03\x07\n\x03\x12\
+ \x03#',\n2\n\x02\x07\x0b\x12\x03%\x045\x1a'\x20Use\x20`bytes::Bytes`\x20\
+ for\x20`bytes`\x20fields\n\n\n\n\x03\x07\x0b\x02\x12\x03\x1d\x07%\n\n\n\
+ \x03\x07\x0b\x04\x12\x03%\x04\x0c\n\n\n\x03\x07\x0b\x05\x12\x03%\r\x11\n\
+ \n\n\x03\x07\x0b\x01\x12\x03%\x12,\n\n\n\x03\x07\x0b\x03\x12\x03%/4\n3\n\
+ \x02\x07\x0c\x12\x03'\x046\x1a(\x20Use\x20`bytes::Bytes`\x20for\x20`stri\
+ ng`\x20fields\n\n\n\n\x03\x07\x0c\x02\x12\x03\x1d\x07%\n\n\n\x03\x07\x0c\
+ \x04\x12\x03'\x04\x0c\n\n\n\x03\x07\x0c\x05\x12\x03'\r\x11\n\n\n\x03\x07\
+ \x0c\x01\x12\x03'\x12-\n\n\n\x03\x07\x0c\x03\x12\x03'05\nJ\n\x02\x07\r\
+ \x12\x03)\x04'\x1a?\x20Use\x20`serde_derive`\x20to\x20implement\x20`Seri\
+ alize`\x20and\x20`Deserialize`\n\n\n\n\x03\x07\r\x02\x12\x03\x1d\x07%\n\
+ \n\n\x03\x07\r\x04\x12\x03)\x04\x0c\n\n\n\x03\x07\r\x05\x12\x03)\r\x11\n\
+ \n\n\x03\x07\r\x01\x12\x03)\x12\x1e\n\n\n\x03\x07\r\x03\x12\x03)!&\n3\n\
+ \x02\x07\x0e\x12\x03+\x04-\x1a(\x20Guard\x20serde\x20annotations\x20with\
+ \x20cfg\x20attr.\n\n\n\n\x03\x07\x0e\x02\x12\x03\x1d\x07%\n\n\n\x03\x07\
+ \x0e\x04\x12\x03+\x04\x0c\n\n\n\x03\x07\x0e\x05\x12\x03+\r\x13\n\n\n\x03\
+ \x07\x0e\x01\x12\x03+\x14$\n\n\n\x03\x07\x0e\x03\x12\x03+',\n\t\n\x01\
+ \x07\x12\x04.\07\x01\nI\n\x02\x07\x0f\x12\x030\x04.\x1a>\x20When\x20true\
+ \x20all\x20fields\x20are\x20public,\x20and\x20not\x20accessors\x20genera\
+ ted\n\n\n\n\x03\x07\x0f\x02\x12\x03.\x07#\n\n\n\x03\x07\x0f\x04\x12\x030\
+ \x04\x0c\n\n\n\x03\x07\x0f\x05\x12\x030\r\x11\n\n\n\x03\x07\x0f\x01\x12\
+ \x030\x12%\n\n\n\x03\x07\x0f\x03\x12\x030(-\nP\n\x02\x07\x10\x12\x032\
+ \x043\x1aE\x20When\x20false,\x20`get_`,\x20`set_`,\x20`mut_`\x20etc.\x20\
+ accessors\x20are\x20not\x20generated\n\n\n\n\x03\x07\x10\x02\x12\x03.\
+ \x07#\n\n\n\x03\x07\x10\x04\x12\x032\x04\x0c\n\n\n\x03\x07\x10\x05\x12\
+ \x032\r\x11\n\n\n\x03\x07\x10\x01\x12\x032\x12*\n\n\n\x03\x07\x10\x03\
+ \x12\x032-2\n2\n\x02\x07\x11\x12\x034\x04;\x1a'\x20Use\x20`bytes::Bytes`\
+ \x20for\x20`bytes`\x20fields\n\n\n\n\x03\x07\x11\x02\x12\x03.\x07#\n\n\n\
+ \x03\x07\x11\x04\x12\x034\x04\x0c\n\n\n\x03\x07\x11\x05\x12\x034\r\x11\n\
+ \n\n\x03\x07\x11\x01\x12\x034\x122\n\n\n\x03\x07\x11\x03\x12\x0345:\n3\n\
+ \x02\x07\x12\x12\x036\x04<\x1a(\x20Use\x20`bytes::Bytes`\x20for\x20`stri\
+ ng`\x20fields\n\n\n\n\x03\x07\x12\x02\x12\x03.\x07#\n\n\n\x03\x07\x12\
+ \x04\x12\x036\x04\x0c\n\n\n\x03\x07\x12\x05\x12\x036\r\x11\n\n\n\x03\x07\
+ \x12\x01\x12\x036\x123\n\n\n\x03\x07\x12\x03\x12\x0366;\n\t\n\x01\x07\
+ \x12\x049\0<\x01\n/\n\x02\x07\x13\x12\x03;\x04-\x1a$\x20use\x20rename_al\
+ l\x20attribute\x20for\x20serde\n\n\n\n\x03\x07\x13\x02\x12\x039\x07\"\n\
+ \n\n\x03\x07\x13\x04\x12\x03;\x04\x0c\n\n\n\x03\x07\x13\x05\x12\x03;\r\
+ \x13\n\n\n\x03\x07\x13\x01\x12\x03;\x14$\n\n\n\x03\x07\x13\x03\x12\x03;'\
+ ,\
";
static file_descriptor_proto_lazy: crate::rt::LazyV2<crate::descriptor::FileDescriptorProto> = crate::rt::LazyV2::INIT;
diff --git a/src/singular.rs b/src/singular.rs
index ef04d2f..1b7e28d 100644
--- a/src/singular.rs
+++ b/src/singular.rs
@@ -1,6 +1,3 @@
-#[cfg(feature = "with-serde")]
-use serde;
-
use std::default::Default;
use std::fmt;
use std::hash::Hash;
@@ -8,6 +5,9 @@ use std::hash::Hasher;
use std::mem;
use std::option;
+#[cfg(feature = "with-serde")]
+use serde;
+
use crate::clear::Clear;
/// Like `Option<T>`, but keeps the actual element on `clear`.
@@ -341,7 +341,9 @@ impl<T: Default + Clear> SingularField<T> {
/// Get contained data, consume self. Return default value for type if this is empty.
#[inline]
pub fn unwrap_or_default(mut self) -> T {
- self.value.clear();
+ if !self.set {
+ self.value.clear();
+ }
self.value
}
@@ -577,4 +579,16 @@ mod test {
x.set_default();
assert_eq!(0, x.as_ref().unwrap().b);
}
+
+ #[test]
+ fn unwrap_or_default() {
+ assert_eq!(
+ "abc",
+ SingularField::some("abc".to_owned()).unwrap_or_default()
+ );
+ assert_eq!("", SingularField::<String>::none().unwrap_or_default());
+ let mut some = SingularField::some("abc".to_owned());
+ some.clear();
+ assert_eq!("", some.unwrap_or_default());
+ }
}
diff --git a/src/text_format/lexer/str_lit.rs b/src/text_format/lexer/str_lit.rs
index caa98f1..15ffa5b 100644
--- a/src/text_format/lexer/str_lit.rs
+++ b/src/text_format/lexer/str_lit.rs
@@ -1,8 +1,9 @@
+use std::fmt;
+use std::string::FromUtf8Error;
+
use super::lexer_impl::Lexer;
use super::lexer_impl::LexerError;
use crate::text_format::lexer::ParserLanguage;
-use std::fmt;
-use std::string::FromUtf8Error;
#[derive(Debug)]
pub enum StrLitDecodeError {
diff --git a/src/text_format/mod.rs b/src/text_format/mod.rs
index 7af03e4..2fa9a16 100644
--- a/src/text_format/mod.rs
+++ b/src/text_format/mod.rs
@@ -19,13 +19,14 @@
//! protobuf implementations, including `protoc` command which can decode
//! and encode messages using text format.
-use crate::message::Message;
-use crate::reflect::ReflectFieldRef;
-use crate::reflect::ReflectValueRef;
use std;
use std::fmt;
use std::fmt::Write;
+use crate::message::Message;
+use crate::reflect::ReflectFieldRef;
+use crate::reflect::ReflectValueRef;
+
mod print;
// Used by text format parser and by pure-rust codegen parsed
diff --git a/src/types.rs b/src/types.rs
index d9bbb10..20244a1 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -4,10 +4,10 @@ use std::marker;
use std::mem;
#[cfg(feature = "bytes")]
-use crate::chars::Chars;
-#[cfg(feature = "bytes")]
use bytes::Bytes;
+#[cfg(feature = "bytes")]
+use crate::chars::Chars;
use crate::coded_input_stream::CodedInputStream;
use crate::coded_output_stream::CodedOutputStream;
use crate::enums::ProtobufEnum;
diff --git a/src/unknown.rs b/src/unknown.rs
index 8e9da12..dd67033 100644
--- a/src/unknown.rs
+++ b/src/unknown.rs
@@ -1,7 +1,3 @@
-use crate::clear::Clear;
-use crate::wire_format;
-use crate::zigzag::encode_zig_zag_32;
-use crate::zigzag::encode_zig_zag_64;
use std::collections::hash_map;
use std::collections::hash_map::DefaultHasher;
use std::collections::HashMap;
@@ -11,6 +7,11 @@ use std::hash::Hash;
use std::hash::Hasher;
use std::slice;
+use crate::clear::Clear;
+use crate::wire_format;
+use crate::zigzag::encode_zig_zag_32;
+use crate::zigzag::encode_zig_zag_64;
+
/// Unknown value.
///
/// See [`UnknownFields`](crate::UnknownFields) for the explanations.
@@ -311,11 +312,12 @@ impl<'s> Iterator for UnknownFieldsIter<'s> {
#[cfg(test)]
mod test {
- use super::UnknownFields;
use std::collections::hash_map::DefaultHasher;
use std::hash::Hash;
use std::hash::Hasher;
+ use super::UnknownFields;
+
#[test]
fn unknown_fields_hash() {
let mut unknown_fields_1 = UnknownFields::new();
diff --git a/src/varint.rs b/src/varint.rs
index 1f1cb1c..8e542bc 100644
--- a/src/varint.rs
+++ b/src/varint.rs
@@ -1,17 +1,21 @@
+use std::mem::MaybeUninit;
+
+use crate::misc::maybe_uninit_write;
+
/// Encode u64 as varint.
/// Panics if buffer length is less than 10.
#[inline]
-pub fn encode_varint64(mut value: u64, buf: &mut [u8]) -> usize {
+pub fn encode_varint64(mut value: u64, buf: &mut [MaybeUninit<u8>]) -> usize {
assert!(buf.len() >= 10);
unsafe {
let mut i = 0;
while (value & !0x7F) > 0 {
- *buf.get_unchecked_mut(i) = ((value & 0x7F) | 0x80) as u8;
+ maybe_uninit_write(buf.get_unchecked_mut(i), ((value & 0x7F) | 0x80) as u8);
value >>= 7;
i += 1;
}
- *buf.get_unchecked_mut(i) = value as u8;
+ maybe_uninit_write(buf.get_unchecked_mut(i), value as u8);
i + 1
}
}
@@ -19,17 +23,17 @@ pub fn encode_varint64(mut value: u64, buf: &mut [u8]) -> usize {
/// Encode u32 value as varint.
/// Panics if buffer length is less than 5.
#[inline]
-pub fn encode_varint32(mut value: u32, buf: &mut [u8]) -> usize {
+pub fn encode_varint32(mut value: u32, buf: &mut [MaybeUninit<u8>]) -> usize {
assert!(buf.len() >= 5);
unsafe {
let mut i = 0;
while (value & !0x7F) > 0 {
- *buf.get_unchecked_mut(i) = ((value & 0x7F) | 0x80) as u8;
+ maybe_uninit_write(buf.get_unchecked_mut(i), ((value & 0x7F) | 0x80) as u8);
value >>= 7;
i += 1;
}
- *buf.get_unchecked_mut(i) = value as u8;
+ maybe_uninit_write(buf.get_unchecked_mut(i), value as u8);
i + 1
}
}
diff --git a/src/well_known_types/any.rs b/src/well_known_types/any.rs
index f306202..e46065f 100644
--- a/src/well_known_types/any.rs
+++ b/src/well_known_types/any.rs
@@ -1,4 +1,4 @@
-// This file is generated by rust-protobuf 2.22.0. Do not edit
+// This file is generated by rust-protobuf 2.26.0. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
diff --git a/src/well_known_types/api.rs b/src/well_known_types/api.rs
index 34798b4..ef97015 100644
--- a/src/well_known_types/api.rs
+++ b/src/well_known_types/api.rs
@@ -1,4 +1,4 @@
-// This file is generated by rust-protobuf 2.22.0. Do not edit
+// This file is generated by rust-protobuf 2.26.0. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
diff --git a/src/well_known_types/duration.rs b/src/well_known_types/duration.rs
index ec82f78..822061a 100644
--- a/src/well_known_types/duration.rs
+++ b/src/well_known_types/duration.rs
@@ -1,4 +1,4 @@
-// This file is generated by rust-protobuf 2.22.0. Do not edit
+// This file is generated by rust-protobuf 2.26.0. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
diff --git a/src/well_known_types/empty.rs b/src/well_known_types/empty.rs
index 5c69487..d55e517 100644
--- a/src/well_known_types/empty.rs
+++ b/src/well_known_types/empty.rs
@@ -1,4 +1,4 @@
-// This file is generated by rust-protobuf 2.22.0. Do not edit
+// This file is generated by rust-protobuf 2.26.0. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
diff --git a/src/well_known_types/field_mask.rs b/src/well_known_types/field_mask.rs
index 9d1f8f6..e98eb53 100644
--- a/src/well_known_types/field_mask.rs
+++ b/src/well_known_types/field_mask.rs
@@ -1,4 +1,4 @@
-// This file is generated by rust-protobuf 2.22.0. Do not edit
+// This file is generated by rust-protobuf 2.26.0. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
diff --git a/src/well_known_types/source_context.rs b/src/well_known_types/source_context.rs
index 55c1ab4..646e87d 100644
--- a/src/well_known_types/source_context.rs
+++ b/src/well_known_types/source_context.rs
@@ -1,4 +1,4 @@
-// This file is generated by rust-protobuf 2.22.0. Do not edit
+// This file is generated by rust-protobuf 2.26.0. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
diff --git a/src/well_known_types/struct_pb.rs b/src/well_known_types/struct_pb.rs
index 222d712..5f18a42 100644
--- a/src/well_known_types/struct_pb.rs
+++ b/src/well_known_types/struct_pb.rs
@@ -1,4 +1,4 @@
-// This file is generated by rust-protobuf 2.22.0. Do not edit
+// This file is generated by rust-protobuf 2.26.0. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
diff --git a/src/well_known_types/timestamp.rs b/src/well_known_types/timestamp.rs
index d0f7903..25e7acf 100644
--- a/src/well_known_types/timestamp.rs
+++ b/src/well_known_types/timestamp.rs
@@ -1,4 +1,4 @@
-// This file is generated by rust-protobuf 2.22.0. Do not edit
+// This file is generated by rust-protobuf 2.26.0. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
diff --git a/src/well_known_types/type_pb.rs b/src/well_known_types/type_pb.rs
index d6c06cc..14bfdb2 100644
--- a/src/well_known_types/type_pb.rs
+++ b/src/well_known_types/type_pb.rs
@@ -1,4 +1,4 @@
-// This file is generated by rust-protobuf 2.22.0. Do not edit
+// This file is generated by rust-protobuf 2.26.0. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
diff --git a/src/well_known_types/wrappers.rs b/src/well_known_types/wrappers.rs
index 11edf4c..4e056c7 100644
--- a/src/well_known_types/wrappers.rs
+++ b/src/well_known_types/wrappers.rs
@@ -1,4 +1,4 @@
-// This file is generated by rust-protobuf 2.22.0. Do not edit
+// This file is generated by rust-protobuf 2.26.0. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702