From 4494b8d49939db61b9e67cbb21990b122bc301fb Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 4 Sep 2024 12:42:57 +0200 Subject: [PATCH 1/6] ZBytes::iter_raw. Improve ZBytes documentation --- examples/examples/z_bytes.rs | 19 +++++++- zenoh/src/api/bytes.rs | 89 +++++++++++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/examples/examples/z_bytes.rs b/examples/examples/z_bytes.rs index ac4a2cc94a..94fc4c0915 100644 --- a/examples/examples/z_bytes.rs +++ b/examples/examples/z_bytes.rs @@ -33,7 +33,8 @@ fn main() { // Corresponding encoding to be used in operations like `.put()`, `.reply()`, etc. // let encoding = Encoding::ZENOH_STRING; - // Cow + // Cow + // See [`zenoh::bytes::ZBytes`] documentation for zero-copy behaviour. let input = Cow::from("test"); let payload = ZBytes::from(&input); let output: Cow = payload.deserialize().unwrap(); @@ -49,6 +50,15 @@ fn main() { // Corresponding encoding to be used in operations like `.put()`, `.reply()`, etc. // let encoding = Encoding::ZENOH_BYTES; + // Cow<[u8]> + // See [`zenoh::bytes::ZBytes`] documentation for zero-copy behaviour. + let input = Cow::from(vec![1, 2, 3, 4]); + let payload = ZBytes::from(&input); + let output: Cow<[u8]> = payload.into(); + assert_eq!(input, output); + // Corresponding encoding to be used in operations like `.put()`, `.reply()`, etc. + // let encoding = Encoding::ZENOH_BYTES; + // Writer & Reader // serialization let mut bytes = ZBytes::empty(); @@ -81,6 +91,13 @@ fn main() { assert_eq!(input[idx], value.unwrap()); } + // Iterator RAW + let input: [i32; 4] = [1, 2, 3, 4]; + let payload = ZBytes::from_iter(input.iter()); + for slice in payload.iter_raw() { + println!("{:02x?}", slice); + } + // HashMap let mut input: HashMap = HashMap::new(); input.insert(0, String::from("abc")); diff --git a/zenoh/src/api/bytes.rs b/zenoh/src/api/bytes.rs index 7e3083b57f..6714adc8f0 100644 --- a/zenoh/src/api/bytes.rs +++ b/zenoh/src/api/bytes.rs @@ -106,7 +106,7 @@ pub trait Deserialize { /// /// `ZBytes` provides convenient methods to the user for serialization/deserialization based on the default Zenoh serializer [`ZSerde`]. /// -/// **NOTE:** Zenoh semantic and protocol take care of sending and receiving bytes without restricting the actual data types. +/// **NOTE 1:** Zenoh semantic and protocol take care of sending and receiving bytes without restricting the actual data types. /// [`ZSerde`] is the default serializer/deserializer provided for convenience to the users to deal with primitives data types via /// a simple out-of-the-box encoding. [`ZSerde`] is **NOT** by any means the only serializer/deserializer users can use nor a limitation /// to the types supported by Zenoh. Users are free and encouraged to use any serializer/deserializer of their choice like *serde*, @@ -185,6 +185,40 @@ pub trait Deserialize { /// assert_eq!(start, end); /// ``` /// +/// **NOTE 2:** `ZBytes` may store data in non-contiguous regions of memory. +/// The typical case for `ZBytes` to store data in different memory regions is when data is received fragmented from the network. +/// The user then can decided to use [`ZBytes::deserialize`], [`ZBytes::reader`], [`ZBytes::into`], or [`ZBytes::iter_raw`] depending +/// on their needs. +/// +/// To directly access raw data as contiguous slice it is preferred to convert `ZBytes` into a [`std::borrow::Cow<[u8]>`]. +/// If `ZBytes` contains all the data in a single memory location, this is guaranteed to be zero-copy. This is the common case for small messages. +/// If `ZBytes` contains data scattered in differnt memory regions, this operation will do an allocation and a copy. This is the common case for large messages. +/// +/// Example: +/// ```rust +/// use std::borrow::Cow; +/// use zenoh::bytes::ZBytes; +/// +/// let buf: Vec = vec![0, 1, 2, 3]; +/// let bytes = ZBytes::from(buf.clone()); +/// let deser: Cow<[u8]> = bytes.into(); +/// assert_eq!(buf.as_slice(), deser.as_ref()); +/// ``` +/// +/// It is also possible to iterate over the raw data that may be scattered on different memory regions. +/// Please note that no guarantee is provided on the internal memory layout of [`ZBytes`] nor on how many slices a given [`ZBytes`] will be composed of. +/// The only provided guarantee is on the bytes order that is preserved. +/// +/// Example: +/// ```rust +/// use zenoh::bytes::ZBytes; +/// +/// let buf: Vec = vec![0, 1, 2, 3]; +/// let bytes = ZBytes::from(buf.clone()); +/// for slice in bytes.iter_raw() { +/// println!("{:02x?}", slice); +/// } +/// ``` #[repr(transparent)] #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct ZBytes(ZBuf); @@ -233,7 +267,19 @@ impl ZBytes { ZBytesWriter(self.0.writer()) } - /// Get a [`ZBytesReader`] implementing [`std::io::Read`] trait. + /// Get a [`ZBytesIterator`] that deserializes a sequence of `T`. + /// + /// Example: + /// ```rust + /// use zenoh::bytes::ZBytes; + /// + /// let list: Vec = vec![1.1, 2.2, 3.3]; + /// let mut zbs = ZBytes::from_iter(list.iter()); + /// + /// for (index, elem) in zbs.iter::().enumerate() { + /// assert_eq!(list[index], elem.unwrap()); + /// } + /// ``` pub fn iter(&self) -> ZBytesIterator<'_, T> where for<'b> ZSerde: Deserialize = &'b ZBytes>, @@ -245,6 +291,43 @@ impl ZBytes { } } + /// Return an iterator on raw bytes slices contained in the [`ZBytes`]. + /// + /// [`ZBytes`] may store data in non-contiguous regions of memory, this iterator + /// then allows to access raw data directly without any attempt of deserializing it. + /// Please note that no guarantee is provided on the internal memory layout of [`ZBytes`]. + /// The only provided guarantee is on the bytes order that is preserved. + /// + /// Please note that [`ZBytes::iter`] will perform deserialization while iterating while [`ZBytes::iter_raw`] will not. + /// + /// ```rust + /// use std::io::Write; + /// use zenoh::bytes::ZBytes; + /// + /// let buf1: Vec = vec![1, 2, 3]; + /// let buf2: Vec = vec![4, 5, 6, 7, 8]; + /// let mut zbs = ZBytes::empty(); + /// let mut writer = zbs.writer(); + /// writer.write(&buf1); + /// writer.write(&buf2); + /// + /// // Print the raw content + /// for slice in zbs.iter_raw() { + /// println!("{:02x?}", slice); + /// } + /// + /// // Concatenate input in a single vector + /// let buf: Vec = buf1.into_iter().chain(buf2.into_iter()).collect(); + /// // Concatenate raw bytes in a single vector + /// let out: Vec = zbs.iter_raw().fold(Vec::new(), |mut b, x| { b.extend_from_slice(x); b }); + /// // The previous line is the equivalent of + /// // let out: Vec = zbs.into(); + /// assert_eq!(buf, out); + /// ``` + pub fn iter_raw(&self) -> impl Iterator { + self.0.slices() + } + /// Serialize an object of type `T` as a [`ZBytes`] using the [`ZSerde`]. /// /// ```rust @@ -294,6 +377,8 @@ impl ZBytes { } /// Deserialize an object of type `T` from a [`Value`] using the [`ZSerde`]. + /// + /// The most efficient to retrieve a contiguous view o pub fn deserialize<'a, T>(&'a self) -> Result>::Error> where ZSerde: Deserialize = &'a ZBytes>, From 070e425c807845f8ef58fa0f51879b078023aa5c Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 4 Sep 2024 12:48:46 +0200 Subject: [PATCH 2/6] Rename iter_raw to slices --- examples/examples/z_bytes.rs | 2 +- zenoh/src/api/bytes.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/examples/z_bytes.rs b/examples/examples/z_bytes.rs index 94fc4c0915..b3c994585e 100644 --- a/examples/examples/z_bytes.rs +++ b/examples/examples/z_bytes.rs @@ -94,7 +94,7 @@ fn main() { // Iterator RAW let input: [i32; 4] = [1, 2, 3, 4]; let payload = ZBytes::from_iter(input.iter()); - for slice in payload.iter_raw() { + for slice in payload.slices() { println!("{:02x?}", slice); } diff --git a/zenoh/src/api/bytes.rs b/zenoh/src/api/bytes.rs index 6714adc8f0..7df78728ab 100644 --- a/zenoh/src/api/bytes.rs +++ b/zenoh/src/api/bytes.rs @@ -187,7 +187,7 @@ pub trait Deserialize { /// /// **NOTE 2:** `ZBytes` may store data in non-contiguous regions of memory. /// The typical case for `ZBytes` to store data in different memory regions is when data is received fragmented from the network. -/// The user then can decided to use [`ZBytes::deserialize`], [`ZBytes::reader`], [`ZBytes::into`], or [`ZBytes::iter_raw`] depending +/// The user then can decided to use [`ZBytes::deserialize`], [`ZBytes::reader`], [`ZBytes::into`], or [`ZBytes::slices`] depending /// on their needs. /// /// To directly access raw data as contiguous slice it is preferred to convert `ZBytes` into a [`std::borrow::Cow<[u8]>`]. @@ -215,7 +215,7 @@ pub trait Deserialize { /// /// let buf: Vec = vec![0, 1, 2, 3]; /// let bytes = ZBytes::from(buf.clone()); -/// for slice in bytes.iter_raw() { +/// for slice in bytes.slices() { /// println!("{:02x?}", slice); /// } /// ``` @@ -298,7 +298,7 @@ impl ZBytes { /// Please note that no guarantee is provided on the internal memory layout of [`ZBytes`]. /// The only provided guarantee is on the bytes order that is preserved. /// - /// Please note that [`ZBytes::iter`] will perform deserialization while iterating while [`ZBytes::iter_raw`] will not. + /// Please note that [`ZBytes::iter`] will perform deserialization while iterating while [`ZBytes::slices`] will not. /// /// ```rust /// use std::io::Write; @@ -312,19 +312,19 @@ impl ZBytes { /// writer.write(&buf2); /// /// // Print the raw content - /// for slice in zbs.iter_raw() { + /// for slice in zbs.slices() { /// println!("{:02x?}", slice); /// } /// /// // Concatenate input in a single vector /// let buf: Vec = buf1.into_iter().chain(buf2.into_iter()).collect(); /// // Concatenate raw bytes in a single vector - /// let out: Vec = zbs.iter_raw().fold(Vec::new(), |mut b, x| { b.extend_from_slice(x); b }); + /// let out: Vec = zbs.slices().fold(Vec::new(), |mut b, x| { b.extend_from_slice(x); b }); /// // The previous line is the equivalent of /// // let out: Vec = zbs.into(); /// assert_eq!(buf, out); /// ``` - pub fn iter_raw(&self) -> impl Iterator { + pub fn slices(&self) -> impl Iterator { self.0.slices() } From 6cbcd34a121be500a7461290611b3aebef7c2897 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 4 Sep 2024 12:51:00 +0200 Subject: [PATCH 3/6] Fix typos --- zenoh/src/api/bytes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zenoh/src/api/bytes.rs b/zenoh/src/api/bytes.rs index 7df78728ab..e0dcef9956 100644 --- a/zenoh/src/api/bytes.rs +++ b/zenoh/src/api/bytes.rs @@ -192,7 +192,7 @@ pub trait Deserialize { /// /// To directly access raw data as contiguous slice it is preferred to convert `ZBytes` into a [`std::borrow::Cow<[u8]>`]. /// If `ZBytes` contains all the data in a single memory location, this is guaranteed to be zero-copy. This is the common case for small messages. -/// If `ZBytes` contains data scattered in differnt memory regions, this operation will do an allocation and a copy. This is the common case for large messages. +/// If `ZBytes` contains data scattered in different memory regions, this operation will do an allocation and a copy. This is the common case for large messages. /// /// Example: /// ```rust From f09a20fc68aaf5a75d0e8ee3b6f908c38c50c809 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 4 Sep 2024 15:33:12 +0200 Subject: [PATCH 4/6] Improve ZBytes docs --- zenoh/src/api/bytes.rs | 68 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/zenoh/src/api/bytes.rs b/zenoh/src/api/bytes.rs index e0dcef9956..6197435e6e 100644 --- a/zenoh/src/api/bytes.rs +++ b/zenoh/src/api/bytes.rs @@ -263,6 +263,8 @@ impl ZBytes { } /// Get a [`ZBytesWriter`] implementing [`std::io::Write`] trait. + /// + /// See [`ZBytesWriter`] on how to chain the serialization of differnt types into a single [`ZBytes`]. pub fn writer(&mut self) -> ZBytesWriter<'_> { ZBytesWriter(self.0.writer()) } @@ -311,7 +313,7 @@ impl ZBytes { /// writer.write(&buf1); /// writer.write(&buf2); /// - /// // Print the raw content + /// // Access the raw content /// for slice in zbs.slices() { /// println!("{:02x?}", slice); /// } @@ -322,7 +324,26 @@ impl ZBytes { /// let out: Vec = zbs.slices().fold(Vec::new(), |mut b, x| { b.extend_from_slice(x); b }); /// // The previous line is the equivalent of /// // let out: Vec = zbs.into(); - /// assert_eq!(buf, out); + /// assert_eq!(buf, out); + /// ``` + /// + /// The example below shows how the [`ZBytesWriter::append`] simply appends the slices of one [`ZBytes`] + /// to another and how those slices can be iterated over to access the raw data. + /// ```rust + /// use std::io::Write; + /// use zenoh::bytes::ZBytes; + /// + /// let buf1: Vec = vec![1, 2, 3]; + /// let buf2: Vec = vec![4, 5, 6, 7, 8]; + /// + /// let mut zbs = ZBytes::empty(); + /// let mut writer = zbs.writer(); + /// writer.append(ZBytes::from(buf1.clone())); + /// writer.append(ZBytes::from(buf2.clone())); + /// + /// let mut iter = zbs.slices(); + /// assert_eq!(buf1.as_slice(), iter.next().unwrap()); + /// assert_eq!(buf2.as_slice(), iter.next().unwrap()); /// ``` pub fn slices(&self) -> impl Iterator { self.0.slices() @@ -376,9 +397,11 @@ impl ZBytes { ZSerde.serialize(t) } - /// Deserialize an object of type `T` from a [`Value`] using the [`ZSerde`]. + /// Deserialize an object of type `T` using [`ZSerde`]. + /// + /// See [`ZBytes::serialize`] and [`ZBytes::try_serialize`] for the examples. /// - /// The most efficient to retrieve a contiguous view o + /// See [`ZBytes::into`] for infallible conversion, e.g. to get raw bytes. pub fn deserialize<'a, T>(&'a self) -> Result>::Error> where ZSerde: Deserialize = &'a ZBytes>, @@ -387,7 +410,7 @@ impl ZBytes { ZSerde.deserialize(self) } - /// Deserialize an object of type `T` from a [`Value`] using the [`ZSerde`]. + /// Deserialize an object of type `T` using [`ZSerde`]. pub fn deserialize_mut<'a, T>(&'a mut self) -> Result>::Error> where ZSerde: Deserialize = &'a mut ZBytes>, @@ -396,7 +419,37 @@ impl ZBytes { ZSerde.deserialize(self) } - /// Infallibly deserialize an object of type `T` from a [`Value`] using the [`ZSerde`]. + /// Infallibly deserialize an object of type `T` using [`ZSerde`]. + /// + /// To directly access raw data as contiguous slice it is preferred to convert `ZBytes` into a [`std::borrow::Cow<[u8]>`](`std::borrow::Cow`). + /// If [`ZBytes`] contains all the data in a single memory location, then it is guaranteed to be zero-copy. This is the common case for small messages. + /// If [`ZBytes`] contains data scattered in different memory regions, this operation will do an allocation and a copy. This is the common case for large messages. + /// + /// ```rust + /// use std::borrow::Cow; + /// use zenoh::bytes::ZBytes; + /// + /// let buf: Vec = vec![0, 1, 2, 3]; + /// let bytes = ZBytes::from(buf.clone()); + /// let deser: Cow<[u8]> = bytes.into(); + /// assert_eq!(buf.as_slice(), deser.as_ref()); + /// ``` + /// + /// An alternative is to convert `ZBytes` into a [`std::vec::Vec`]. + /// Converting to [`std::vec::Vec`] will always allocate and make a copy. + /// + /// ```rust + /// use std::borrow::Cow; + /// use zenoh::bytes::ZBytes; + /// + /// let buf: Vec = vec![0, 1, 2, 3]; + /// let bytes = ZBytes::from(buf.clone()); + /// let deser: Vec = bytes.into(); + /// assert_eq!(buf.as_slice(), deser.as_slice()); + /// ``` + /// + /// If you want to be sure that no copy is performed at all, then you should use [`ZBytes::slices`]. + /// Please note that in this case data may not be contiguous in memory and it is the responsability of the user to properly parse the raw slices. pub fn into<'a, T>(&'a self) -> T where ZSerde: Deserialize = &'a ZBytes, Error = Infallible>, @@ -405,7 +458,7 @@ impl ZBytes { ZSerde.deserialize(self).unwrap_infallible() } - /// Infallibly deserialize an object of type `T` from a [`Value`] using the [`ZSerde`]. + /// Infallibly deserialize an object of type `T` using the [`ZSerde`]. pub fn into_mut<'a, T>(&'a mut self) -> T where ZSerde: Deserialize = &'a mut ZBytes, Error = Infallible>, @@ -1249,6 +1302,7 @@ impl From<&mut Cow<'_, str>> for ZBytes { } } +/// See [`Deserialize>`] for guarantees on copies. impl<'a> Deserialize> for ZSerde { type Input<'b> = &'a ZBytes; type Error = Utf8Error; From f8a7576fc6bed60bafeb8dff314d894814391594 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 4 Sep 2024 15:33:12 +0200 Subject: [PATCH 5/6] Improve ZBytes docs --- zenoh/src/api/bytes.rs | 72 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/zenoh/src/api/bytes.rs b/zenoh/src/api/bytes.rs index e0dcef9956..476f440512 100644 --- a/zenoh/src/api/bytes.rs +++ b/zenoh/src/api/bytes.rs @@ -242,7 +242,7 @@ impl ZBytes { self.0.is_empty() } - /// Returns the length of the ZBytes. + /// Returns the total number of bytes in the ZBytes. pub fn len(&self) -> usize { self.0.len() } @@ -263,6 +263,8 @@ impl ZBytes { } /// Get a [`ZBytesWriter`] implementing [`std::io::Write`] trait. + /// + /// See [`ZBytesWriter`] on how to chain the serialization of differnt types into a single [`ZBytes`]. pub fn writer(&mut self) -> ZBytesWriter<'_> { ZBytesWriter(self.0.writer()) } @@ -311,7 +313,7 @@ impl ZBytes { /// writer.write(&buf1); /// writer.write(&buf2); /// - /// // Print the raw content + /// // Access the raw content /// for slice in zbs.slices() { /// println!("{:02x?}", slice); /// } @@ -322,7 +324,26 @@ impl ZBytes { /// let out: Vec = zbs.slices().fold(Vec::new(), |mut b, x| { b.extend_from_slice(x); b }); /// // The previous line is the equivalent of /// // let out: Vec = zbs.into(); - /// assert_eq!(buf, out); + /// assert_eq!(buf, out); + /// ``` + /// + /// The example below shows how the [`ZBytesWriter::append`] simply appends the slices of one [`ZBytes`] + /// to another and how those slices can be iterated over to access the raw data. + /// ```rust + /// use std::io::Write; + /// use zenoh::bytes::ZBytes; + /// + /// let buf1: Vec = vec![1, 2, 3]; + /// let buf2: Vec = vec![4, 5, 6, 7, 8]; + /// + /// let mut zbs = ZBytes::empty(); + /// let mut writer = zbs.writer(); + /// writer.append(ZBytes::from(buf1.clone())); + /// writer.append(ZBytes::from(buf2.clone())); + /// + /// let mut iter = zbs.slices(); + /// assert_eq!(buf1.as_slice(), iter.next().unwrap()); + /// assert_eq!(buf2.as_slice(), iter.next().unwrap()); /// ``` pub fn slices(&self) -> impl Iterator { self.0.slices() @@ -376,9 +397,11 @@ impl ZBytes { ZSerde.serialize(t) } - /// Deserialize an object of type `T` from a [`Value`] using the [`ZSerde`]. + /// Deserialize an object of type `T` using [`ZSerde`]. + /// + /// See [`ZBytes::serialize`] and [`ZBytes::try_serialize`] for the examples. /// - /// The most efficient to retrieve a contiguous view o + /// See [`ZBytes::into`] for infallible conversion, e.g. to get raw bytes. pub fn deserialize<'a, T>(&'a self) -> Result>::Error> where ZSerde: Deserialize = &'a ZBytes>, @@ -387,7 +410,7 @@ impl ZBytes { ZSerde.deserialize(self) } - /// Deserialize an object of type `T` from a [`Value`] using the [`ZSerde`]. + /// Deserialize an object of type `T` using [`ZSerde`]. pub fn deserialize_mut<'a, T>(&'a mut self) -> Result>::Error> where ZSerde: Deserialize = &'a mut ZBytes>, @@ -396,7 +419,37 @@ impl ZBytes { ZSerde.deserialize(self) } - /// Infallibly deserialize an object of type `T` from a [`Value`] using the [`ZSerde`]. + /// Infallibly deserialize an object of type `T` using [`ZSerde`]. + /// + /// To directly access raw data as contiguous slice it is preferred to convert `ZBytes` into a [`std::borrow::Cow<[u8]>`](`std::borrow::Cow`). + /// If [`ZBytes`] contains all the data in a single memory location, then it is guaranteed to be zero-copy. This is the common case for small messages. + /// If [`ZBytes`] contains data scattered in different memory regions, this operation will do an allocation and a copy. This is the common case for large messages. + /// + /// ```rust + /// use std::borrow::Cow; + /// use zenoh::bytes::ZBytes; + /// + /// let buf: Vec = vec![0, 1, 2, 3]; + /// let bytes = ZBytes::from(buf.clone()); + /// let deser: Cow<[u8]> = bytes.into(); + /// assert_eq!(buf.as_slice(), deser.as_ref()); + /// ``` + /// + /// An alternative is to convert `ZBytes` into a [`std::vec::Vec`]. + /// Converting to [`std::vec::Vec`] will always allocate and make a copy. + /// + /// ```rust + /// use std::borrow::Cow; + /// use zenoh::bytes::ZBytes; + /// + /// let buf: Vec = vec![0, 1, 2, 3]; + /// let bytes = ZBytes::from(buf.clone()); + /// let deser: Vec = bytes.into(); + /// assert_eq!(buf.as_slice(), deser.as_slice()); + /// ``` + /// + /// If you want to be sure that no copy is performed at all, then you should use [`ZBytes::slices`]. + /// Please note that in this case data may not be contiguous in memory and it is the responsability of the user to properly parse the raw slices. pub fn into<'a, T>(&'a self) -> T where ZSerde: Deserialize = &'a ZBytes, Error = Infallible>, @@ -405,7 +458,7 @@ impl ZBytes { ZSerde.deserialize(self).unwrap_infallible() } - /// Infallibly deserialize an object of type `T` from a [`Value`] using the [`ZSerde`]. + /// Infallibly deserialize an object of type `T` using the [`ZSerde`]. pub fn into_mut<'a, T>(&'a mut self) -> T where ZSerde: Deserialize = &'a mut ZBytes, Error = Infallible>, @@ -638,7 +691,7 @@ where } /// The default serializer for [`ZBytes`]. It supports primitives types, such as: `Vec`, `uX`, `iX`, `fX`, `String`, `bool`. -/// It also supports common Rust serde values like `serde_json::Value`. +/// It also supports common Rust serde values like [`serde_json::Value`]. /// /// **NOTE:** Zenoh semantic and protocol take care of sending and receiving bytes without restricting the actual data types. /// [`ZSerde`] is the default serializer/deserializer provided for convenience to the users to deal with primitives data types via @@ -1249,6 +1302,7 @@ impl From<&mut Cow<'_, str>> for ZBytes { } } +/// See [`Deserialize>`] for guarantees on copies. impl<'a> Deserialize> for ZSerde { type Input<'b> = &'a ZBytes; type Error = Utf8Error; From 7b5f9ae03ca059e425009b91b89dbf42db85d506 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 4 Sep 2024 15:53:07 +0200 Subject: [PATCH 6/6] Fix typos --- zenoh/src/api/bytes.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zenoh/src/api/bytes.rs b/zenoh/src/api/bytes.rs index 476f440512..9595a70d23 100644 --- a/zenoh/src/api/bytes.rs +++ b/zenoh/src/api/bytes.rs @@ -264,7 +264,7 @@ impl ZBytes { /// Get a [`ZBytesWriter`] implementing [`std::io::Write`] trait. /// - /// See [`ZBytesWriter`] on how to chain the serialization of differnt types into a single [`ZBytes`]. + /// See [`ZBytesWriter`] on how to chain the serialization of different types into a single [`ZBytes`]. pub fn writer(&mut self) -> ZBytesWriter<'_> { ZBytesWriter(self.0.writer()) } @@ -449,7 +449,7 @@ impl ZBytes { /// ``` /// /// If you want to be sure that no copy is performed at all, then you should use [`ZBytes::slices`]. - /// Please note that in this case data may not be contiguous in memory and it is the responsability of the user to properly parse the raw slices. + /// Please note that in this case data may not be contiguous in memory and it is the responsibility of the user to properly parse the raw slices. pub fn into<'a, T>(&'a self) -> T where ZSerde: Deserialize = &'a ZBytes, Error = Infallible>,