Skip to content

RUST-2258 Use borrowed buffer in raw serializer #590

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ pub use self::{
},
ser::{
serialize_to_bson,
serialize_to_buffer,
serialize_to_document,
serialize_to_raw_document_buf,
serialize_to_vec,
Expand Down
16 changes: 14 additions & 2 deletions src/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,19 @@ pub fn serialize_to_vec<T>(value: &T) -> Result<Vec<u8>>
where
T: Serialize,
{
let mut serializer = raw::Serializer::new();
let mut bytes = Vec::new();
serialize_to_buffer(value, &mut bytes)?;
Ok(bytes)
}

/// Serialize the given `T` as a BSON byte vector into the provided byte buffer.
/// This allows reusing the same buffer for multiple serializations.
#[inline]
pub fn serialize_to_buffer<T>(value: &T, buffer: &mut Vec<u8>) -> Result<()>
where
T: Serialize,
{
let mut serializer = raw::Serializer::new(buffer);
#[cfg(feature = "serde_path_to_error")]
{
serde_path_to_error::serialize(value, &mut serializer).map_err(Error::with_path)?;
Expand All @@ -98,7 +110,7 @@ where
{
value.serialize(&mut serializer)?;
}
Ok(serializer.into_vec())
Ok(())
}

/// Serialize the given `T` as a [`RawDocumentBuf`].
Expand Down
60 changes: 30 additions & 30 deletions src/ser/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ use crate::{
use document_serializer::DocumentSerializer;

/// Serializer used to convert a type `T` into raw BSON bytes.
pub(crate) struct Serializer {
bytes: Vec<u8>,
pub(crate) struct Serializer<'a> {
bytes: &'a mut Vec<u8>,

/// The index into `bytes` where the current serialization started.
start_index: usize,

/// The index into `bytes` where the current element type will need to be stored.
/// This needs to be set retroactively because in BSON, the element type comes before the key,
Expand Down Expand Up @@ -58,21 +61,18 @@ impl SerializerHint {
}
}

impl Serializer {
pub(crate) fn new() -> Self {
impl<'a> Serializer<'a> {
pub(crate) fn new(bytes: &'a mut Vec<u8>) -> Self {
let start_index = bytes.len();
Self {
bytes: Vec::new(),
type_index: 0,
bytes,
start_index,
type_index: start_index,
hint: SerializerHint::None,
human_readable: false,
}
}

/// Convert this serializer into the vec of the serialized bytes.
pub(crate) fn into_vec(self) -> Vec<u8> {
self.bytes
}

/// Reserve a spot for the element type to be set retroactively via `update_element_type`.
#[inline]
fn reserve_element_type(&mut self) {
Expand All @@ -83,7 +83,7 @@ impl Serializer {
/// Retroactively set the element type of the most recently serialized element.
#[inline]
fn update_element_type(&mut self, t: ElementType) -> Result<()> {
if self.type_index == 0 {
if self.type_index == self.start_index {
if matches!(t, ElementType::EmbeddedDocument) {
// don't need to set the element type for the top level document
return Ok(());
Expand Down Expand Up @@ -113,17 +113,17 @@ impl Serializer {
}
}

impl<'a> serde::Serializer for &'a mut Serializer {
impl<'a, 'b> serde::Serializer for &'a mut Serializer<'b> {
type Ok = ();
type Error = Error;

type SerializeSeq = DocumentSerializer<'a>;
type SerializeTuple = DocumentSerializer<'a>;
type SerializeTupleStruct = DocumentSerializer<'a>;
type SerializeTupleVariant = VariantSerializer<'a>;
type SerializeMap = DocumentSerializer<'a>;
type SerializeStruct = StructSerializer<'a>;
type SerializeStructVariant = VariantSerializer<'a>;
type SerializeSeq = DocumentSerializer<'a, 'b>;
type SerializeTuple = DocumentSerializer<'a, 'b>;
type SerializeTupleStruct = DocumentSerializer<'a, 'b>;
type SerializeTupleVariant = VariantSerializer<'a, 'b>;
type SerializeMap = DocumentSerializer<'a, 'b>;
type SerializeStruct = StructSerializer<'a, 'b>;
type SerializeStructVariant = VariantSerializer<'a, 'b>;

fn is_human_readable(&self) -> bool {
self.human_readable
Expand Down Expand Up @@ -385,15 +385,15 @@ impl<'a> serde::Serializer for &'a mut Serializer {
}
}

pub(crate) enum StructSerializer<'a> {
pub(crate) enum StructSerializer<'a, 'b> {
/// Serialize a BSON value currently represented in serde as a struct (e.g. ObjectId)
Value(ValueSerializer<'a>),
Value(ValueSerializer<'a, 'b>),

/// Serialize the struct as a document.
Document(DocumentSerializer<'a>),
Document(DocumentSerializer<'a, 'b>),
}

impl SerializeStruct for StructSerializer<'_> {
impl SerializeStruct for StructSerializer<'_, '_> {
type Ok = ();
type Error = Error;

Expand Down Expand Up @@ -424,8 +424,8 @@ enum VariantInnerType {

/// Serializer used for enum variants, including both tuple (e.g. Foo::Bar(1, 2, 3)) and
/// struct (e.g. Foo::Bar { a: 1 }).
pub(crate) struct VariantSerializer<'a> {
root_serializer: &'a mut Serializer,
pub(crate) struct VariantSerializer<'a, 'b> {
root_serializer: &'a mut Serializer<'b>,

/// Variants are serialized as documents of the form `{ <variant name>: <document or array> }`,
/// and `doc_start` indicates the index at which the outer document begins.
Expand All @@ -438,8 +438,8 @@ pub(crate) struct VariantSerializer<'a> {
num_elements_serialized: usize,
}

impl<'a> VariantSerializer<'a> {
fn start(rs: &'a mut Serializer, variant: &'static CStr, inner_type: VariantInnerType) -> Self {
impl<'a, 'b> VariantSerializer<'a, 'b> {
fn start(rs: &'a mut Serializer<'b>, variant: &'static CStr, inner_type: VariantInnerType) -> Self {
let doc_start = rs.bytes.len();
// write placeholder length for document, will be updated at end
static ZERO: RawBsonRef = RawBsonRef::Int32(0);
Expand Down Expand Up @@ -492,7 +492,7 @@ impl<'a> VariantSerializer<'a> {
}
}

impl serde::ser::SerializeTupleVariant for VariantSerializer<'_> {
impl serde::ser::SerializeTupleVariant for VariantSerializer<'_, '_> {
type Ok = ();

type Error = Error;
Expand All @@ -511,7 +511,7 @@ impl serde::ser::SerializeTupleVariant for VariantSerializer<'_> {
}
}

impl serde::ser::SerializeStructVariant for VariantSerializer<'_> {
impl serde::ser::SerializeStructVariant for VariantSerializer<'_, '_> {
type Ok = ();

type Error = Error;
Expand Down
32 changes: 16 additions & 16 deletions src/ser/raw/document_serializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ use crate::{

use super::Serializer;

pub(crate) struct DocumentSerializationResult<'a> {
pub(crate) root_serializer: &'a mut Serializer,
pub(crate) struct DocumentSerializationResult<'a, 'b> {
pub(crate) root_serializer: &'a mut Serializer<'b>,
}

/// Serializer used to serialize document or array bodies.
pub(crate) struct DocumentSerializer<'a> {
root_serializer: &'a mut Serializer,
pub(crate) struct DocumentSerializer<'a, 'b> {
root_serializer: &'a mut Serializer<'b>,
num_keys_serialized: usize,
start: usize,
}

impl<'a> DocumentSerializer<'a> {
pub(crate) fn start(rs: &'a mut Serializer) -> Self {
impl<'a, 'b> DocumentSerializer<'a, 'b> {
pub(crate) fn start(rs: &'a mut Serializer<'b>) -> Self {
let start = rs.bytes.len();
RawBsonRef::Int32(0).append_to(&mut rs.bytes);
Self {
Expand All @@ -30,7 +30,7 @@ impl<'a> DocumentSerializer<'a> {
}

/// Serialize a document key using the provided closure.
fn serialize_doc_key_custom<F: FnOnce(&mut Serializer) -> Result<()>>(
fn serialize_doc_key_custom<F: FnOnce(&mut Serializer<'b>) -> Result<()>>(
&mut self,
f: F,
) -> Result<()> {
Expand All @@ -55,7 +55,7 @@ impl<'a> DocumentSerializer<'a> {
Ok(())
}

pub(crate) fn end_doc(self) -> crate::ser::Result<DocumentSerializationResult<'a>> {
pub(crate) fn end_doc(self) -> crate::ser::Result<DocumentSerializationResult<'a, 'b>> {
self.root_serializer.bytes.push(0);
let length = (self.root_serializer.bytes.len() - self.start) as i32;
self.root_serializer.replace_i32(self.start, length);
Expand All @@ -65,7 +65,7 @@ impl<'a> DocumentSerializer<'a> {
}
}

impl serde::ser::SerializeSeq for DocumentSerializer<'_> {
impl serde::ser::SerializeSeq for DocumentSerializer<'_, '_> {
type Ok = ();
type Error = Error;

Expand All @@ -90,7 +90,7 @@ impl serde::ser::SerializeSeq for DocumentSerializer<'_> {
}
}

impl serde::ser::SerializeMap for DocumentSerializer<'_> {
impl serde::ser::SerializeMap for DocumentSerializer<'_, '_> {
type Ok = ();

type Error = Error;
Expand All @@ -116,7 +116,7 @@ impl serde::ser::SerializeMap for DocumentSerializer<'_> {
}
}

impl serde::ser::SerializeStruct for DocumentSerializer<'_> {
impl serde::ser::SerializeStruct for DocumentSerializer<'_, '_> {
type Ok = ();

type Error = Error;
Expand All @@ -136,7 +136,7 @@ impl serde::ser::SerializeStruct for DocumentSerializer<'_> {
}
}

impl serde::ser::SerializeTuple for DocumentSerializer<'_> {
impl serde::ser::SerializeTuple for DocumentSerializer<'_, '_> {
type Ok = ();

type Error = Error;
Expand All @@ -156,7 +156,7 @@ impl serde::ser::SerializeTuple for DocumentSerializer<'_> {
}
}

impl serde::ser::SerializeTupleStruct for DocumentSerializer<'_> {
impl serde::ser::SerializeTupleStruct for DocumentSerializer<'_, '_> {
type Ok = ();

type Error = Error;
Expand All @@ -178,11 +178,11 @@ impl serde::ser::SerializeTupleStruct for DocumentSerializer<'_> {

/// Serializer used specifically for serializing document keys.
/// Only keys that serialize to strings will be accepted.
struct KeySerializer<'a> {
root_serializer: &'a mut Serializer,
struct KeySerializer<'a, 'b> {
root_serializer: &'a mut Serializer<'b>,
}

impl serde::Serializer for KeySerializer<'_> {
impl serde::Serializer for KeySerializer<'_, '_> {
type Ok = ();

type Error = Error;
Expand Down
24 changes: 12 additions & 12 deletions src/ser/raw/value_serializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use super::{document_serializer::DocumentSerializer, Serializer};

/// A serializer used specifically for serializing the serde-data-model form of a BSON type (e.g.
/// [`Binary`]) to raw bytes.
pub(crate) struct ValueSerializer<'a> {
root_serializer: &'a mut Serializer,
pub(crate) struct ValueSerializer<'a, 'b> {
root_serializer: &'a mut Serializer<'b>,
state: SerializationStep,
}

Expand Down Expand Up @@ -124,8 +124,8 @@ impl From<ValueType> for ElementType {
}
}

impl<'a> ValueSerializer<'a> {
pub(super) fn new(rs: &'a mut Serializer, value_type: ValueType) -> Self {
impl<'a, 'b> ValueSerializer<'a, 'b> {
pub(super) fn new(rs: &'a mut Serializer<'b>, value_type: ValueType) -> Self {
let state = match value_type {
ValueType::DateTime => SerializationStep::DateTime,
ValueType::Binary => SerializationStep::Binary,
Expand Down Expand Up @@ -155,15 +155,15 @@ impl<'a> ValueSerializer<'a> {
}
}

impl<'b> serde::Serializer for &'b mut ValueSerializer<'_> {
impl<'a, 'b> serde::Serializer for &'a mut ValueSerializer<'_, 'b> {
type Ok = ();
type Error = Error;

type SerializeSeq = Impossible<(), Error>;
type SerializeTuple = Impossible<(), Error>;
type SerializeTupleStruct = Impossible<(), Error>;
type SerializeTupleVariant = Impossible<(), Error>;
type SerializeMap = CodeWithScopeSerializer<'b>;
type SerializeMap = CodeWithScopeSerializer<'a, 'b>;
type SerializeStruct = Self;
type SerializeStructVariant = Impossible<(), Error>;

Expand Down Expand Up @@ -475,7 +475,7 @@ impl<'b> serde::Serializer for &'b mut ValueSerializer<'_> {
}
}

impl SerializeStruct for &mut ValueSerializer<'_> {
impl SerializeStruct for &mut ValueSerializer<'_, '_> {
type Ok = ();
type Error = Error;

Expand Down Expand Up @@ -605,14 +605,14 @@ impl SerializeStruct for &mut ValueSerializer<'_> {
}
}

pub(crate) struct CodeWithScopeSerializer<'a> {
pub(crate) struct CodeWithScopeSerializer<'a, 'b> {
start: usize,
doc: DocumentSerializer<'a>,
doc: DocumentSerializer<'a, 'b>,
}

impl<'a> CodeWithScopeSerializer<'a> {
impl<'a, 'b> CodeWithScopeSerializer<'a, 'b> {
#[inline]
fn start(code: &str, rs: &'a mut Serializer) -> Self {
fn start(code: &str, rs: &'a mut Serializer<'b>) -> Self {
let start = rs.bytes.len();
RawBsonRef::Int32(0).append_to(&mut rs.bytes); // placeholder length
write_string(&mut rs.bytes, code);
Expand All @@ -622,7 +622,7 @@ impl<'a> CodeWithScopeSerializer<'a> {
}
}

impl SerializeMap for CodeWithScopeSerializer<'_> {
impl SerializeMap for CodeWithScopeSerializer<'_, '_> {
type Ok = ();
type Error = Error;

Expand Down