jiacai2050 commented on code in PR #1628: URL: https://github.com/apache/horaedb/pull/1628#discussion_r2459288511
########## src/benchmarks/src/bin/pooled_parser_mem.rs: ########## @@ -0,0 +1,60 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! pooled parser memory bench. + +use benchmarks::util::{MemoryBenchConfig, MemoryStats}; +use remote_write::pooled_parser::PooledParser; +use tikv_jemallocator::Jemalloc; + +#[global_allocator] +static ALLOC: Jemalloc = Jemalloc; + +#[tokio::main(flavor = "current_thread")] +async fn main() -> Result<(), Box<dyn std::error::Error>> { Review Comment: All those files under `bin` have similar structure, could you refactor then into one file and use params to choose which method to decode the data? ########## src/remote_write/src/pooled_parser.rs: ########## @@ -0,0 +1,221 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! Pooled parser for Prometheus remote write requests. +//! +//! This crate parses the protobuf `string` type as Rust `Bytes` instances +//! instead of `String` instances to avoid allocation, and it **does not** +//! perform UTF-8 validation when parsing. Therefore, it is up to the caller to +//! decide how to make use of the parsed `Bytes` and whether to apply UTF-8 +//! validation. +//! +//! ## Basic Usage Review Comment: I prefer we remove all comments below L26 , the API is not stable now, and very likely the comments become out of date when we refactor the API. ########## src/remote_write/src/pooled_parser.rs: ########## @@ -0,0 +1,221 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! Pooled parser for Prometheus remote write requests. +//! +//! This crate parses the protobuf `string` type as Rust `Bytes` instances +//! instead of `String` instances to avoid allocation, and it **does not** +//! perform UTF-8 validation when parsing. Therefore, it is up to the caller to +//! decide how to make use of the parsed `Bytes` and whether to apply UTF-8 +//! validation. +//! +//! ## Basic Usage +//! +//! Synchronous parse: +//! +//! ```rust +//! use bytes::Bytes; +//! use remote_write::pooled_parser::PooledParser; +//! # use std::error::Error; +//! # fn main() -> Result<(), Box<dyn Error>> { +//! # let data = Bytes::new(); +//! +//! let parser = PooledParser::default(); +//! let request = parser.decode(data.clone())?; // Return a `PooledWriteRequest` instance. +//! +//! # Ok(()) +//! # } +//! ``` +//! +//! Asynchronous parse: +//! +//! ```rust +//! use bytes::Bytes; +//! use remote_write::pooled_parser::PooledParser; +//! # use std::error::Error; +//! # #[tokio::main] +//! # async fn main() -> Result<(), Box<dyn Error>> { +//! # let data = Bytes::new(); +//! let parser = PooledParser::default(); +//! let request = parser.decode_async(data).await?; // Return a deadpool object wrapper. +//! +//! // Access the parsed data through the deadpool object wrapper. +//! println!("Parsed {} timeseries", request.timeseries.len()); +//! for ts in &request.timeseries { +//! for label in &ts.labels { +//! let name = String::from_utf8_lossy(&label.name); +//! let value = String::from_utf8_lossy(&label.value); +//! println!("Label: {}={}", name, value); +//! } +//! } +//! // Object automatically returned to the pool when dropped. +//! # Ok(()) +//! # } +//! ``` +//! +//! Note: if you use `decode_async()`, you need to add `deadpool` to your +//! dependencies: +//! +//! ```toml +//! [dependencies] +//! deadpool = { workspace = true } # or "0.10" if not inside this workspace. +//! ``` +//! +//! ## Enable Unsafe Optimization +//! +//! ```toml +//! [dependencies] +//! remote_write = { path = ".", features = ["unsafe-split"] } +//! ``` +//! +//! This feature enables zero-copy bytes split that bypasses Rust's memory +//! safety guarantees. The parsed `Bytes` instances **cannot outlive** the +//! input raw protobuf `Bytes` instance. +//! +//! Correct usage example: +//! +//! ```rust,no_run +//! use bytes::Bytes; +//! use remote_write::pooled_parser::PooledParser; +//! # use std::error::Error; +//! // CORRECT: consume immediately. +//! async fn foo() -> Result<Vec<String>, Box<dyn Error>> { +//! # fn load_protobuf_data() -> Bytes { Bytes::new() } +//! let raw_data = load_protobuf_data(); // Bytes. +//! let parser = PooledParser::default(); +//! let request = parser.decode_async(raw_data).await?; +//! +//! let metric_names: Vec<String> = request +//! .timeseries +//! .iter() +//! .flat_map(|ts| ts.labels.iter()) +//! .filter(|label| label.name.as_ref() == b"__name__") +//! .filter_map(|label| String::from_utf8(label.value.to_vec()).ok()) +//! .collect(); +//! +//! Ok(metric_names) +//! } +//! ``` +//! +//! Wrong usage example: +//! +//! ```rust,ignore +//! // WRONG: returned parsed data outlives the input. +//! fn bar() -> PooledWriteRequest { +//! let raw_data = load_protobuf_data(); // Bytes +//! let parser = PooledParser::default(); +//! parser.decode(raw_data).unwrap() +//! // The input `raw_data` is dropped here, but the returned `PooledWriteRequest` outlives it. +//! } +//! ``` + +use bytes::Bytes; + +use crate::{ + pb_reader::read_write_request, + pooled_types::{PooledWriteRequest, WriteRequestManager, POOL}, + repeated_field::Clear, +}; + +#[derive(Debug, Clone)] +pub struct PooledParser; + +impl PooledParser { + fn new() -> Self { + Self + } + + /// Decode a [`PooledWriteRequest`] from the buffer and return it. + /// + /// This method will allocate a new [`PooledWriteRequest`] instance since it + /// is unable to use the object pool in sync functions. + /// + /// # Example Review Comment: Delete comment below, the reason is the same as before. ########## src/remote_write/src/pooled_types.rs: ########## @@ -0,0 +1,192 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +use async_trait::async_trait; +use bytes::Bytes; +use deadpool::managed::{Manager, Metrics, Pool, RecycleResult}; +use once_cell::sync::Lazy; + +use crate::repeated_field::{Clear, RepeatedField}; + +#[derive(Debug, Clone)] +pub struct PooledLabel { Review Comment: Name this `Label`, same to other structures in this file. We shouldn't add the Pooled prefix just because it's used in Pool, it could be used in a non-pool case. ########## src/remote_write/src/pooled_parser.rs: ########## @@ -0,0 +1,221 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! Pooled parser for Prometheus remote write requests. +//! +//! This crate parses the protobuf `string` type as Rust `Bytes` instances +//! instead of `String` instances to avoid allocation, and it **does not** +//! perform UTF-8 validation when parsing. Therefore, it is up to the caller to +//! decide how to make use of the parsed `Bytes` and whether to apply UTF-8 +//! validation. +//! +//! ## Basic Usage +//! +//! Synchronous parse: +//! +//! ```rust +//! use bytes::Bytes; +//! use remote_write::pooled_parser::PooledParser; +//! # use std::error::Error; +//! # fn main() -> Result<(), Box<dyn Error>> { +//! # let data = Bytes::new(); +//! +//! let parser = PooledParser::default(); +//! let request = parser.decode(data.clone())?; // Return a `PooledWriteRequest` instance. +//! +//! # Ok(()) +//! # } +//! ``` +//! +//! Asynchronous parse: +//! +//! ```rust +//! use bytes::Bytes; +//! use remote_write::pooled_parser::PooledParser; +//! # use std::error::Error; +//! # #[tokio::main] +//! # async fn main() -> Result<(), Box<dyn Error>> { +//! # let data = Bytes::new(); +//! let parser = PooledParser::default(); +//! let request = parser.decode_async(data).await?; // Return a deadpool object wrapper. +//! +//! // Access the parsed data through the deadpool object wrapper. +//! println!("Parsed {} timeseries", request.timeseries.len()); +//! for ts in &request.timeseries { +//! for label in &ts.labels { +//! let name = String::from_utf8_lossy(&label.name); +//! let value = String::from_utf8_lossy(&label.value); +//! println!("Label: {}={}", name, value); +//! } +//! } +//! // Object automatically returned to the pool when dropped. +//! # Ok(()) +//! # } +//! ``` +//! +//! Note: if you use `decode_async()`, you need to add `deadpool` to your +//! dependencies: +//! +//! ```toml +//! [dependencies] +//! deadpool = { workspace = true } # or "0.10" if not inside this workspace. +//! ``` +//! +//! ## Enable Unsafe Optimization +//! +//! ```toml +//! [dependencies] +//! remote_write = { path = ".", features = ["unsafe-split"] } +//! ``` +//! +//! This feature enables zero-copy bytes split that bypasses Rust's memory +//! safety guarantees. The parsed `Bytes` instances **cannot outlive** the +//! input raw protobuf `Bytes` instance. +//! +//! Correct usage example: +//! +//! ```rust,no_run +//! use bytes::Bytes; +//! use remote_write::pooled_parser::PooledParser; +//! # use std::error::Error; +//! // CORRECT: consume immediately. +//! async fn foo() -> Result<Vec<String>, Box<dyn Error>> { +//! # fn load_protobuf_data() -> Bytes { Bytes::new() } +//! let raw_data = load_protobuf_data(); // Bytes. +//! let parser = PooledParser::default(); +//! let request = parser.decode_async(raw_data).await?; +//! +//! let metric_names: Vec<String> = request +//! .timeseries +//! .iter() +//! .flat_map(|ts| ts.labels.iter()) +//! .filter(|label| label.name.as_ref() == b"__name__") +//! .filter_map(|label| String::from_utf8(label.value.to_vec()).ok()) +//! .collect(); +//! +//! Ok(metric_names) +//! } +//! ``` +//! +//! Wrong usage example: +//! +//! ```rust,ignore +//! // WRONG: returned parsed data outlives the input. +//! fn bar() -> PooledWriteRequest { +//! let raw_data = load_protobuf_data(); // Bytes +//! let parser = PooledParser::default(); +//! parser.decode(raw_data).unwrap() +//! // The input `raw_data` is dropped here, but the returned `PooledWriteRequest` outlives it. +//! } +//! ``` + +use bytes::Bytes; + +use crate::{ + pb_reader::read_write_request, + pooled_types::{PooledWriteRequest, WriteRequestManager, POOL}, + repeated_field::Clear, +}; + +#[derive(Debug, Clone)] +pub struct PooledParser; + +impl PooledParser { + fn new() -> Self { + Self + } + + /// Decode a [`PooledWriteRequest`] from the buffer and return it. + /// + /// This method will allocate a new [`PooledWriteRequest`] instance since it + /// is unable to use the object pool in sync functions. + /// + /// # Example + /// + /// ```rust + /// use bytes::Bytes; + /// use remote_write::pooled_parser::PooledParser; + /// # use std::error::Error; + /// # fn main() -> Result<(), Box<dyn Error>> { + /// # let data = Bytes::new(); + /// + /// let parser = PooledParser::default(); + /// let request = parser.decode(data)?; + /// + /// # Ok(()) + /// # } + /// ``` + pub fn decode(&self, buf: Bytes) -> Result<PooledWriteRequest, String> { + // Cannot get a PooledWriteRequest instance from the pool in sync functions. + let mut request = PooledWriteRequest::default(); + read_write_request(buf, &mut request).map_err(|e| e.to_string())?; + Ok(request) + } + + /// Decode a [`PooledWriteRequest`] from the buffer and return a + /// [`deadpool::managed::Object`] wrapper. + /// + /// This method will reuse a [`PooledWriteRequest`] instance from the object + /// pool. After the returned object is dropped, it will be returned to the + /// pool. + /// + /// # Example + /// + /// ```rust,no_run + /// use bytes::Bytes; + /// use remote_write::pooled_parser::PooledParser; + /// # use std::error::Error; + /// # #[tokio::main] + /// # async fn main() -> Result<(), Box<dyn Error>> { + /// # let data = Bytes::new(); + /// + /// let parser = PooledParser::default(); + /// let request = parser.decode_async(data).await?; + /// + /// // Access the parsed data through the deadpool object wrapper. + /// println!("Parsed {} timeseries", request.timeseries.len()); + /// for ts in &request.timeseries { + /// for label in &ts.labels { + /// let name = String::from_utf8_lossy(&label.name); + /// let value = String::from_utf8_lossy(&label.value); + /// println!("Label: {}={}", name, value); + /// } + /// } + /// // Object automatically returned to the pool when dropped. + /// + /// # Ok(()) + /// # } + /// ``` + pub async fn decode_async( Review Comment: We don't need this async functions, the encode/decode is a CPU-bound work, use async has little benefits. ########## src/remote_write/src/pooled_parser.rs: ########## @@ -0,0 +1,221 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! Pooled parser for Prometheus remote write requests. +//! +//! This crate parses the protobuf `string` type as Rust `Bytes` instances +//! instead of `String` instances to avoid allocation, and it **does not** +//! perform UTF-8 validation when parsing. Therefore, it is up to the caller to +//! decide how to make use of the parsed `Bytes` and whether to apply UTF-8 +//! validation. +//! +//! ## Basic Usage +//! +//! Synchronous parse: +//! +//! ```rust +//! use bytes::Bytes; +//! use remote_write::pooled_parser::PooledParser; +//! # use std::error::Error; +//! # fn main() -> Result<(), Box<dyn Error>> { +//! # let data = Bytes::new(); +//! +//! let parser = PooledParser::default(); +//! let request = parser.decode(data.clone())?; // Return a `PooledWriteRequest` instance. +//! +//! # Ok(()) +//! # } +//! ``` +//! +//! Asynchronous parse: +//! +//! ```rust +//! use bytes::Bytes; +//! use remote_write::pooled_parser::PooledParser; +//! # use std::error::Error; +//! # #[tokio::main] +//! # async fn main() -> Result<(), Box<dyn Error>> { +//! # let data = Bytes::new(); +//! let parser = PooledParser::default(); +//! let request = parser.decode_async(data).await?; // Return a deadpool object wrapper. +//! +//! // Access the parsed data through the deadpool object wrapper. +//! println!("Parsed {} timeseries", request.timeseries.len()); +//! for ts in &request.timeseries { +//! for label in &ts.labels { +//! let name = String::from_utf8_lossy(&label.name); +//! let value = String::from_utf8_lossy(&label.value); +//! println!("Label: {}={}", name, value); +//! } +//! } +//! // Object automatically returned to the pool when dropped. +//! # Ok(()) +//! # } +//! ``` +//! +//! Note: if you use `decode_async()`, you need to add `deadpool` to your +//! dependencies: +//! +//! ```toml +//! [dependencies] +//! deadpool = { workspace = true } # or "0.10" if not inside this workspace. +//! ``` +//! +//! ## Enable Unsafe Optimization +//! +//! ```toml +//! [dependencies] +//! remote_write = { path = ".", features = ["unsafe-split"] } +//! ``` +//! +//! This feature enables zero-copy bytes split that bypasses Rust's memory +//! safety guarantees. The parsed `Bytes` instances **cannot outlive** the +//! input raw protobuf `Bytes` instance. +//! +//! Correct usage example: +//! +//! ```rust,no_run +//! use bytes::Bytes; +//! use remote_write::pooled_parser::PooledParser; +//! # use std::error::Error; +//! // CORRECT: consume immediately. +//! async fn foo() -> Result<Vec<String>, Box<dyn Error>> { +//! # fn load_protobuf_data() -> Bytes { Bytes::new() } +//! let raw_data = load_protobuf_data(); // Bytes. +//! let parser = PooledParser::default(); +//! let request = parser.decode_async(raw_data).await?; +//! +//! let metric_names: Vec<String> = request +//! .timeseries +//! .iter() +//! .flat_map(|ts| ts.labels.iter()) +//! .filter(|label| label.name.as_ref() == b"__name__") +//! .filter_map(|label| String::from_utf8(label.value.to_vec()).ok()) +//! .collect(); +//! +//! Ok(metric_names) +//! } +//! ``` +//! +//! Wrong usage example: +//! +//! ```rust,ignore +//! // WRONG: returned parsed data outlives the input. +//! fn bar() -> PooledWriteRequest { +//! let raw_data = load_protobuf_data(); // Bytes +//! let parser = PooledParser::default(); +//! parser.decode(raw_data).unwrap() +//! // The input `raw_data` is dropped here, but the returned `PooledWriteRequest` outlives it. +//! } +//! ``` + +use bytes::Bytes; + +use crate::{ + pb_reader::read_write_request, + pooled_types::{PooledWriteRequest, WriteRequestManager, POOL}, + repeated_field::Clear, +}; + +#[derive(Debug, Clone)] +pub struct PooledParser; + +impl PooledParser { + fn new() -> Self { + Self + } + + /// Decode a [`PooledWriteRequest`] from the buffer and return it. + /// + /// This method will allocate a new [`PooledWriteRequest`] instance since it + /// is unable to use the object pool in sync functions. + /// + /// # Example + /// + /// ```rust + /// use bytes::Bytes; + /// use remote_write::pooled_parser::PooledParser; + /// # use std::error::Error; + /// # fn main() -> Result<(), Box<dyn Error>> { + /// # let data = Bytes::new(); + /// + /// let parser = PooledParser::default(); + /// let request = parser.decode(data)?; + /// + /// # Ok(()) + /// # } + /// ``` + pub fn decode(&self, buf: Bytes) -> Result<PooledWriteRequest, String> { Review Comment: I prefer we use anyhow as the Error type for this crate, it has more features like backtrace. ########## src/remote_write/README.md: ########## @@ -0,0 +1,380 @@ +# Remote Write Parser + +A hand-written [Prometheus Remote Write Request (V1)](https://prometheus.io/docs/specs/prw/remote_write_spec/) parser optimized for zero-allocation parsing. It receives protobuf data as `Bytes` and returns a parsed `WriteRequest` instance. + +## Implementation + +Key optimization techniques: + +- Object pooling backed by deadpool. + +- `RepeatedField` data structures. + +- Zero-copy bytes split backed by unsafe. + +- Manual loop unrolling and function inline optimization. + +## Usage + +This crate parses the protobuf `string` type as Rust `Bytes` instances instead of `String` instances to avoid allocation, and it **does not** perform UTF-8 validation when parsing. Also, it **does not** check the semantics of the parsed data, such as [Labels](https://prometheus.io/docs/specs/prw/remote_write_spec/#labels). Therefore, it is up to the caller to decide how to make use of the parsed `Bytes` and whether to apply extra validation or error handling. + +### Basic Usage Review Comment: Delete this section ########## src/remote_write/tests/equivalence_test.rs: ########## @@ -0,0 +1,177 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! This test is used to verify the correctness of the pooled parser rigorously +//! (50 iterations, 25 iterations for each input data), by comparing the results +//! with the prost parser. +//! +//! Test with `--features unsafe-split` to enable the unsafe optimization. + +use std::{fs, sync::Arc}; + +use bytes::Bytes; +use pb_types::{Exemplar, Label, MetricMetadata, Sample, TimeSeries, WriteRequest}; +use prost::Message; +use remote_write::pooled_parser::PooledParser; +use tokio::task::JoinHandle; + +const ITERATIONS: usize = 50; + +fn load_test_data() -> (Bytes, Bytes) { + let data1 = Bytes::from( + fs::read("tests/workloads/1709380533560664458.data").expect("test data load failed"), + ); + + let data2 = Bytes::from( + fs::read("tests/workloads/1709380533705807779.data").expect("test data load failed"), + ); + + (data1, data2) +} + +fn parse_with_prost(data: &Bytes) -> WriteRequest { + WriteRequest::decode(data.clone()).expect("prost decode failed") +} + +async fn parse_with_pooled(data: &Bytes) -> WriteRequest { + let data_copy = data.clone(); + let parser = PooledParser; + let pooled_request = parser + .decode_async(data_copy) + .await + .expect("pooled decode failed"); + + // Convert pooled types to pb_types to compare with prost. + let mut write_request = WriteRequest { + timeseries: Vec::new(), + metadata: Vec::new(), + }; + + for pooled_ts in pooled_request.timeseries.iter() { Review Comment: ```suggestion for pooled_ts in &pooled_request.timeseries { ``` The same changes apply to for loops below also. ########## src/remote_write/src/repeated_field.rs: ########## @@ -0,0 +1,530 @@ +// Copyright (c) 2019 Stepan Koltsov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +/// ! The [Clear] trait and [RepeatedField] are taken from [rust-protobuf](https://github.com/stepancheg/rust-protobuf/tree/master/protobuf-examples/vs-prost) +/// to leverage the pooling mechanism to avoid frequent heap +/// allocation/deallocation when decoding deeply nested structs. +use std::borrow::Borrow; +use std::{ + cmp::Ordering, + default::Default, + fmt, + hash::{Hash, Hasher}, + iter::{FromIterator, IntoIterator}, + ops::{Deref, DerefMut, Index, IndexMut}, + slice, vec, +}; + +use bytes::Bytes; + +/// anything that can be cleared +pub trait Clear { + /// Clear this make, make it equivalent to newly created object. + fn clear(&mut self); +} + +impl<T> Clear for Option<T> { + fn clear(&mut self) { Review Comment: Please update the comments as suggested by copilot. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
