You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: zenoh/src/api/bytes.rs
+147-8Lines changed: 147 additions & 8 deletions
Original file line number
Diff line number
Diff line change
@@ -106,7 +106,7 @@ pub trait Deserialize<T> {
106
106
///
107
107
/// `ZBytes` provides convenient methods to the user for serialization/deserialization based on the default Zenoh serializer [`ZSerde`].
108
108
///
109
-
/// **NOTE:** Zenoh semantic and protocol take care of sending and receiving bytes without restricting the actual data types.
109
+
/// **NOTE 1:** Zenoh semantic and protocol take care of sending and receiving bytes without restricting the actual data types.
110
110
/// [`ZSerde`] is the default serializer/deserializer provided for convenience to the users to deal with primitives data types via
111
111
/// a simple out-of-the-box encoding. [`ZSerde`] is **NOT** by any means the only serializer/deserializer users can use nor a limitation
112
112
/// 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<T> {
185
185
/// assert_eq!(start, end);
186
186
/// ```
187
187
///
188
+
/// **NOTE 2:** `ZBytes` may store data in non-contiguous regions of memory.
189
+
/// The typical case for `ZBytes` to store data in different memory regions is when data is received fragmented from the network.
190
+
/// The user then can decided to use [`ZBytes::deserialize`], [`ZBytes::reader`], [`ZBytes::into`], or [`ZBytes::slices`] depending
191
+
/// on their needs.
192
+
///
193
+
/// To directly access raw data as contiguous slice it is preferred to convert `ZBytes` into a [`std::borrow::Cow<[u8]>`].
194
+
/// 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.
195
+
/// 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.
196
+
///
197
+
/// Example:
198
+
/// ```rust
199
+
/// use std::borrow::Cow;
200
+
/// use zenoh::bytes::ZBytes;
201
+
///
202
+
/// let buf: Vec<u8> = vec![0, 1, 2, 3];
203
+
/// let bytes = ZBytes::from(buf.clone());
204
+
/// let deser: Cow<[u8]> = bytes.into();
205
+
/// assert_eq!(buf.as_slice(), deser.as_ref());
206
+
/// ```
207
+
///
208
+
/// It is also possible to iterate over the raw data that may be scattered on different memory regions.
209
+
/// 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.
210
+
/// The only provided guarantee is on the bytes order that is preserved.
211
+
///
212
+
/// Example:
213
+
/// ```rust
214
+
/// use zenoh::bytes::ZBytes;
215
+
///
216
+
/// let buf: Vec<u8> = vec![0, 1, 2, 3];
217
+
/// let bytes = ZBytes::from(buf.clone());
218
+
/// for slice in bytes.slices() {
219
+
/// println!("{:02x?}", slice);
220
+
/// }
221
+
/// ```
188
222
#[repr(transparent)]
189
223
#[derive(Clone,Debug,Default,PartialEq,Eq)]
190
224
pubstructZBytes(ZBuf);
@@ -208,7 +242,7 @@ impl ZBytes {
208
242
self.0.is_empty()
209
243
}
210
244
211
-
/// Returns the length of the ZBytes.
245
+
/// Returns the total number of bytes in the ZBytes.
212
246
pubfnlen(&self) -> usize{
213
247
self.0.len()
214
248
}
@@ -229,11 +263,25 @@ impl ZBytes {
229
263
}
230
264
231
265
/// Get a [`ZBytesWriter`] implementing [`std::io::Write`] trait.
266
+
///
267
+
/// See [`ZBytesWriter`] on how to chain the serialization of different types into a single [`ZBytes`].
232
268
pubfnwriter(&mutself) -> ZBytesWriter<'_>{
233
269
ZBytesWriter(self.0.writer())
234
270
}
235
271
236
-
/// Get a [`ZBytesReader`] implementing [`std::io::Read`] trait.
272
+
/// Get a [`ZBytesIterator`] that deserializes a sequence of `T`.
273
+
///
274
+
/// Example:
275
+
/// ```rust
276
+
/// use zenoh::bytes::ZBytes;
277
+
///
278
+
/// let list: Vec<f32> = vec![1.1, 2.2, 3.3];
279
+
/// let mut zbs = ZBytes::from_iter(list.iter());
280
+
///
281
+
/// for (index, elem) in zbs.iter::<f32>().enumerate() {
/// Infallibly deserialize an object of type `T` from a [`Value`] using the [`ZSerde`].
422
+
/// Infallibly deserialize an object of type `T` using [`ZSerde`].
423
+
///
424
+
/// To directly access raw data as contiguous slice it is preferred to convert `ZBytes` into a [`std::borrow::Cow<[u8]>`](`std::borrow::Cow`).
425
+
/// 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.
426
+
/// 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.
427
+
///
428
+
/// ```rust
429
+
/// use std::borrow::Cow;
430
+
/// use zenoh::bytes::ZBytes;
431
+
///
432
+
/// let buf: Vec<u8> = vec![0, 1, 2, 3];
433
+
/// let bytes = ZBytes::from(buf.clone());
434
+
/// let deser: Cow<[u8]> = bytes.into();
435
+
/// assert_eq!(buf.as_slice(), deser.as_ref());
436
+
/// ```
437
+
///
438
+
/// An alternative is to convert `ZBytes` into a [`std::vec::Vec<u8>`].
439
+
/// Converting to [`std::vec::Vec<u8>`] will always allocate and make a copy.
440
+
///
441
+
/// ```rust
442
+
/// use std::borrow::Cow;
443
+
/// use zenoh::bytes::ZBytes;
444
+
///
445
+
/// let buf: Vec<u8> = vec![0, 1, 2, 3];
446
+
/// let bytes = ZBytes::from(buf.clone());
447
+
/// let deser: Vec<u8> = bytes.into();
448
+
/// assert_eq!(buf.as_slice(), deser.as_slice());
449
+
/// ```
450
+
///
451
+
/// If you want to be sure that no copy is performed at all, then you should use [`ZBytes::slices`].
452
+
/// 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.
0 commit comments