From 5aedd2c09219073895ab1fcd105f2fb2b05a5d86 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Mon, 8 Apr 2024 18:01:43 +0200 Subject: [PATCH 01/19] Payload tuple generic impl --- Cargo.lock | 7 + Cargo.toml | 1 + zenoh/Cargo.toml | 1 + zenoh/src/payload.rs | 1143 ++++++++++++++++++++++++++++++++++++--- zenoh/src/queryable.rs | 1 + zenoh/src/session.rs | 13 +- zenoh/src/subscriber.rs | 3 - 7 files changed, 1093 insertions(+), 76 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d3ea8978b5..3f74af9ed1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3954,6 +3954,12 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "unwrap-infallible" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151ac09978d3c2862c4e39b557f4eceee2cc72150bc4cb4f16abf061b6e381fb" + [[package]] name = "unzip-n" version = "0.1.2" @@ -4479,6 +4485,7 @@ dependencies = [ "tokio", "tokio-util", "uhlc", + "unwrap-infallible", "uuid", "vec_map", "zenoh-buffers", diff --git a/Cargo.toml b/Cargo.toml index 9210c96b70..d02f84eca8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -159,6 +159,7 @@ tokio-rustls = "0.25.0" console-subscriber = "0.2" typenum = "1.16.0" uhlc = { version = "0.7.0", default-features = false } # Default features are disabled due to usage in no_std crates +unwrap-infallible = "0.1.5" unzip-n = "0.1.2" url = "2.3.1" urlencoding = "2.1.2" diff --git a/zenoh/Cargo.toml b/zenoh/Cargo.toml index d20a4b914e..80cf8ba1bc 100644 --- a/zenoh/Cargo.toml +++ b/zenoh/Cargo.toml @@ -90,6 +90,7 @@ serde_yaml = { workspace = true } socket2 = { workspace = true } stop-token = { workspace = true } uhlc = { workspace = true, features = ["default"] } +unwrap-infallible = { workspace = true } uuid = { workspace = true, features = ["default"] } vec_map = { workspace = true } zenoh-buffers = { workspace = true, features = ["std"] } diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index ed2a58145c..db3126d93d 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -14,17 +14,38 @@ //! Payload primitives. use crate::buffers::ZBuf; +use std::marker::PhantomData; use std::{ borrow::Cow, convert::Infallible, fmt::Debug, ops::Deref, string::FromUtf8Error, sync::Arc, }; -use zenoh_buffers::buffer::Buffer; +use unwrap_infallible::UnwrapInfallible; use zenoh_buffers::{ - buffer::SplitBuffer, reader::HasReader, writer::HasWriter, ZBufReader, ZSlice, + buffer::{Buffer, SplitBuffer}, + reader::{HasReader, Reader}, + writer::HasWriter, + ZBufReader, ZSlice, }; -use zenoh_result::ZResult; +use zenoh_codec::{RCodec, WCodec, Zenoh080}; +use zenoh_result::{ZError, ZResult}; #[cfg(feature = "shared-memory")] use zenoh_shm::SharedMemoryBuf; +/// Trait to encode a type `T` into a [`Value`]. +pub trait Serialize { + type Output; + + /// The implementer should take care of serializing the type `T` and set the proper [`Encoding`]. + fn serialize(self, t: T) -> Self::Output; +} + +pub trait Deserialize<'a, T> { + type Error; + + /// The implementer should take care of deserializing the type `T` based on the [`Encoding`] information. + fn deserialize(self, t: &'a Payload) -> Result; +} + +/// A payload contains the serialized bytes of user data. #[repr(transparent)] #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct Payload(ZBuf); @@ -57,14 +78,17 @@ impl Payload { pub fn reader(&self) -> PayloadReader<'_> { PayloadReader(self.0.reader()) } -} - -/// A reader that implements [`std::io::Read`] trait to read from a [`Payload`]. -pub struct PayloadReader<'a>(ZBufReader<'a>); -impl std::io::Read for PayloadReader<'_> { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - self.0.read(buf) + /// Get a [`PayloadReader`] implementing [`std::io::Read`] trait. + pub fn iter(&self) -> PayloadIterator<'_, T> + where + T: TryFrom, + ZSerde: for<'b> Deserialize<'b, T, Error = ZDeserializeError>, + { + PayloadIterator { + reader: self.0.reader(), + _t: PhantomData::, + } } } @@ -99,19 +123,45 @@ impl Payload { } } -/// Trait to encode a type `T` into a [`Value`]. -pub trait Serialize { - type Output; +/// A reader that implements [`std::io::Read`] trait to read from a [`Payload`]. +pub struct PayloadReader<'a>(ZBufReader<'a>); - /// The implementer should take care of serializing the type `T` and set the proper [`Encoding`]. - fn serialize(self, t: T) -> Self::Output; +impl std::io::Read for PayloadReader<'_> { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + std::io::Read::read(&mut self.0, buf) + } } -pub trait Deserialize<'a, T> { - type Error; +/// An iterator that implements [`std::iter::Iterator`] trait to iterate on values `T` in a [`Payload`]. +/// Note that [`Payload`] contains a serialized version of `T` and iterating over a [`Payload`] performs lazy deserialization. +pub struct PayloadIterator<'a, T> +where + ZSerde: Deserialize<'a, T>, +{ + reader: ZBufReader<'a>, + _t: PhantomData, +} - /// The implementer should take care of deserializing the type `T` based on the [`Encoding`] information. - fn deserialize(self, t: &'a Payload) -> Result; +impl<'a, T> Iterator for PayloadIterator<'a, T> +where + ZSerde: for<'b> Deserialize<'b, T, Error = ZDeserializeError>, +{ + type Item = T; + + fn next(&mut self) -> Option { + let codec = Zenoh080::new(); + + let kbuf: ZBuf = codec.read(&mut self.reader).ok()?; + let kpld = Payload::new(kbuf); + + let t = ZSerde.deserialize(&kpld).ok()?; + Some(t) + } + + fn size_hint(&self) -> (usize, Option) { + let remaining = self.reader.remaining(); + (remaining, Some(remaining)) + } } /// The default serializer for Zenoh payload. It supports primitives types, such as: vec, int, uint, float, string, bool. @@ -122,7 +172,7 @@ pub struct ZSerde; #[derive(Debug, Clone, Copy)] pub struct ZDeserializeError; -// Bytes +// ZBuf impl Serialize for ZSerde { type Output = Payload; @@ -131,9 +181,9 @@ impl Serialize for ZSerde { } } -impl From for ZBuf { - fn from(value: Payload) -> Self { - value.0 +impl From for Payload { + fn from(t: ZBuf) -> Self { + ZSerde.serialize(t) } } @@ -141,16 +191,23 @@ impl Deserialize<'_, ZBuf> for ZSerde { type Error = Infallible; fn deserialize(self, v: &Payload) -> Result { - Ok(v.into()) + Ok(v.0.clone()) + } +} + +impl From for ZBuf { + fn from(value: Payload) -> Self { + value.0 } } impl From<&Payload> for ZBuf { fn from(value: &Payload) -> Self { - value.0.clone() + ZSerde.deserialize(value).unwrap_infallible() } } +// Vec impl Serialize> for ZSerde { type Output = Payload; @@ -159,11 +216,9 @@ impl Serialize> for ZSerde { } } -impl Serialize<&[u8]> for ZSerde { - type Output = Payload; - - fn serialize(self, t: &[u8]) -> Self::Output { - Payload::new(t.to_vec()) +impl From> for Payload { + fn from(t: Vec) -> Self { + ZSerde.serialize(t) } } @@ -171,16 +226,38 @@ impl Deserialize<'_, Vec> for ZSerde { type Error = Infallible; fn deserialize(self, v: &Payload) -> Result, Self::Error> { - Ok(Vec::from(v)) + Ok(v.0.contiguous().to_vec()) + } +} + +impl From for Vec { + fn from(value: Payload) -> Self { + ZSerde.deserialize(&value).unwrap_infallible() } } impl From<&Payload> for Vec { fn from(value: &Payload) -> Self { - Cow::from(value).to_vec() + ZSerde.deserialize(value).unwrap_infallible() } } +// &[u8] +impl Serialize<&[u8]> for ZSerde { + type Output = Payload; + + fn serialize(self, t: &[u8]) -> Self::Output { + Payload::new(t.to_vec()) + } +} + +impl From<&[u8]> for Payload { + fn from(t: &[u8]) -> Self { + ZSerde.serialize(t) + } +} + +// Cow<[u8]> impl<'a> Serialize> for ZSerde { type Output = Payload; @@ -189,6 +266,12 @@ impl<'a> Serialize> for ZSerde { } } +impl From> for Payload { + fn from(t: Cow<'_, [u8]>) -> Self { + ZSerde.serialize(t) + } +} + impl<'a> Deserialize<'a, Cow<'a, [u8]>> for ZSerde { type Error = Infallible; @@ -199,7 +282,7 @@ impl<'a> Deserialize<'a, Cow<'a, [u8]>> for ZSerde { impl<'a> From<&'a Payload> for Cow<'a, [u8]> { fn from(value: &'a Payload) -> Self { - value.0.contiguous() + ZSerde.deserialize(value).unwrap_infallible() } } @@ -212,11 +295,9 @@ impl Serialize for ZSerde { } } -impl Serialize<&str> for ZSerde { - type Output = Payload; - - fn serialize(self, s: &str) -> Self::Output { - Self.serialize(s.to_string()) +impl From for Payload { + fn from(t: String) -> Self { + ZSerde.serialize(t) } } @@ -224,7 +305,16 @@ impl Deserialize<'_, String> for ZSerde { type Error = FromUtf8Error; fn deserialize(self, v: &Payload) -> Result { - String::from_utf8(Vec::from(v)) + let v: Vec = ZSerde.deserialize(v).unwrap_infallible(); + String::from_utf8(v) + } +} + +impl TryFrom for String { + type Error = FromUtf8Error; + + fn try_from(value: Payload) -> Result { + ZSerde.deserialize(&value) } } @@ -236,14 +326,22 @@ impl TryFrom<&Payload> for String { } } -impl TryFrom for String { - type Error = FromUtf8Error; +// &str +impl Serialize<&str> for ZSerde { + type Output = Payload; - fn try_from(value: Payload) -> Result { - ZSerde.deserialize(&value) + fn serialize(self, s: &str) -> Self::Output { + Self.serialize(s.to_string()) } } +impl From<&str> for Payload { + fn from(t: &str) -> Self { + ZSerde.serialize(t) + } +} + +// Cow impl<'a> Serialize> for ZSerde { type Output = Payload; @@ -252,6 +350,12 @@ impl<'a> Serialize> for ZSerde { } } +impl From> for Payload { + fn from(t: Cow<'_, str>) -> Self { + ZSerde.serialize(t) + } +} + impl<'a> Deserialize<'a, Cow<'a, str>> for ZSerde { type Error = FromUtf8Error; @@ -277,7 +381,11 @@ macro_rules! impl_int { fn serialize(self, t: $t) -> Self::Output { let bs = t.to_le_bytes(); - let end = 1 + bs.iter().rposition(|b| *b != 0).unwrap_or(bs.len() - 1); + let end = if t == 0 as $t { + 0 + } else { + 1 + bs.iter().rposition(|b| *b != 0).unwrap_or(bs.len() - 1) + }; // SAFETY: // - 0 is a valid start index because bs is guaranteed to always have a length greater or equal than 1 // - end is a valid end index because is bounded between 0 and bs.len() @@ -285,6 +393,12 @@ macro_rules! impl_int { } } + impl From<$t> for Payload { + fn from(t: $t) -> Self { + ZSerde.serialize(t) + } + } + impl Serialize<&$t> for ZSerde { type Output = Payload; @@ -293,11 +407,23 @@ macro_rules! impl_int { } } + impl From<&$t> for Payload { + fn from(t: &$t) -> Self { + ZSerde.serialize(t) + } + } + impl Serialize<&mut $t> for ZSerde { type Output = Payload; fn serialize(self, t: &mut $t) -> Self::Output { - Self.serialize(*t) + ZSerde.serialize(*t) + } + } + + impl From<&mut $t> for Payload { + fn from(t: &mut $t) -> Self { + ZSerde.serialize(t) } } @@ -319,6 +445,14 @@ macro_rules! impl_int { } } + impl TryFrom for $t { + type Error = ZDeserializeError; + + fn try_from(value: Payload) -> Result { + ZSerde.deserialize(&value) + } + } + impl TryFrom<&Payload> for $t { type Error = ZDeserializeError; @@ -349,12 +483,18 @@ impl_int!(f64, ZSerde::ZENOH_FLOAT); // Zenoh bool impl Serialize for ZSerde { - type Output = ZBuf; + type Output = Payload; fn serialize(self, t: bool) -> Self::Output { // SAFETY: casting a bool into an integer is well-defined behaviour. // 0 is false, 1 is true: https://doc.rust-lang.org/std/primitive.bool.html - ZBuf::from((t as u8).to_le_bytes()) + Payload::new(ZBuf::from((t as u8).to_le_bytes())) + } +} + +impl From for Payload { + fn from(t: bool) -> Self { + ZSerde.serialize(t) } } @@ -391,6 +531,14 @@ impl Serialize<&serde_json::Value> for ZSerde { } } +impl TryFrom<&serde_json::Value> for Payload { + type Error = serde_json::Error; + + fn try_from(value: &serde_json::Value) -> Result { + ZSerde.serialize(value) + } +} + impl Serialize for ZSerde { type Output = Result; @@ -399,6 +547,14 @@ impl Serialize for ZSerde { } } +impl TryFrom for Payload { + type Error = serde_json::Error; + + fn try_from(value: serde_json::Value) -> Result { + ZSerde.serialize(value) + } +} + impl Deserialize<'_, serde_json::Value> for ZSerde { type Error = serde_json::Error; @@ -407,11 +563,11 @@ impl Deserialize<'_, serde_json::Value> for ZSerde { } } -impl TryFrom for Payload { +impl TryFrom<&Payload> for serde_json::Value { type Error = serde_json::Error; - fn try_from(value: serde_json::Value) -> Result { - ZSerde.serialize(value) + fn try_from(value: &Payload) -> Result { + ZSerde.deserialize(value) } } @@ -426,6 +582,14 @@ impl Serialize<&serde_yaml::Value> for ZSerde { } } +impl TryFrom<&serde_yaml::Value> for Payload { + type Error = serde_yaml::Error; + + fn try_from(value: &serde_yaml::Value) -> Result { + ZSerde.serialize(value) + } +} + impl Serialize for ZSerde { type Output = Result; @@ -434,6 +598,14 @@ impl Serialize for ZSerde { } } +impl TryFrom for Payload { + type Error = serde_yaml::Error; + + fn try_from(value: serde_yaml::Value) -> Result { + ZSerde.serialize(value) + } +} + impl Deserialize<'_, serde_yaml::Value> for ZSerde { type Error = serde_yaml::Error; @@ -442,11 +614,11 @@ impl Deserialize<'_, serde_yaml::Value> for ZSerde { } } -impl TryFrom for Payload { +impl TryFrom<&Payload> for serde_yaml::Value { type Error = serde_yaml::Error; - fn try_from(value: serde_yaml::Value) -> Result { - ZSerde.serialize(value) + fn try_from(value: &Payload) -> Result { + ZSerde.deserialize(value) } } @@ -461,6 +633,14 @@ impl Serialize<&serde_cbor::Value> for ZSerde { } } +impl TryFrom<&serde_cbor::Value> for Payload { + type Error = serde_cbor::Error; + + fn try_from(value: &serde_cbor::Value) -> Result { + ZSerde.serialize(value) + } +} + impl Serialize for ZSerde { type Output = Result; @@ -469,6 +649,14 @@ impl Serialize for ZSerde { } } +impl TryFrom for Payload { + type Error = serde_cbor::Error; + + fn try_from(value: serde_cbor::Value) -> Result { + ZSerde.serialize(value) + } +} + impl Deserialize<'_, serde_cbor::Value> for ZSerde { type Error = serde_cbor::Error; @@ -477,11 +665,11 @@ impl Deserialize<'_, serde_cbor::Value> for ZSerde { } } -impl TryFrom for Payload { +impl TryFrom<&Payload> for serde_cbor::Value { type Error = serde_cbor::Error; - fn try_from(value: serde_cbor::Value) -> Result { - ZSerde.serialize(value) + fn try_from(value: &Payload) -> Result { + ZSerde.deserialize(value) } } @@ -500,6 +688,14 @@ impl Serialize<&serde_pickle::Value> for ZSerde { } } +impl TryFrom<&serde_pickle::Value> for Payload { + type Error = serde_pickle::Error; + + fn try_from(value: &serde_pickle::Value) -> Result { + ZSerde.serialize(value) + } +} + impl Serialize for ZSerde { type Output = Result; @@ -508,6 +704,14 @@ impl Serialize for ZSerde { } } +impl TryFrom for Payload { + type Error = serde_pickle::Error; + + fn try_from(value: serde_pickle::Value) -> Result { + ZSerde.serialize(value) + } +} + impl Deserialize<'_, serde_pickle::Value> for ZSerde { type Error = serde_pickle::Error; @@ -516,11 +720,11 @@ impl Deserialize<'_, serde_pickle::Value> for ZSerde { } } -impl TryFrom for Payload { +impl TryFrom<&Payload> for serde_pickle::Value { type Error = serde_pickle::Error; - fn try_from(value: serde_pickle::Value) -> Result { - ZSerde.serialize(value) + fn try_from(value: &Payload) -> Result { + ZSerde.deserialize(value) } } @@ -553,15 +757,86 @@ impl Serialize for ZSerde { } } -impl From for Payload +// Tuple +impl Serialize<(A, B)> for ZSerde where - ZSerde: Serialize, + A: Into, + B: Into, { - fn from(t: T) -> Self { - ZSerde.serialize(t) + type Output = Payload; + + fn serialize(self, t: (A, B)) -> Self::Output { + let (a, b) = t; + + let codec = Zenoh080::new(); + let mut buffer: ZBuf = ZBuf::empty(); + let mut writer = buffer.writer(); + let apld: Payload = a.into(); + let bpld: Payload = b.into(); + + // SAFETY: we are serializing slices on a ZBuf, so serialization will never + // fail unless we run out of memory. In that case, Rust memory allocator + // will panic before the serializer has any chance to fail. + unsafe { + codec.write(&mut writer, &apld.0).unwrap_unchecked(); + codec.write(&mut writer, &bpld.0).unwrap_unchecked(); + } + + Payload::new(buffer) + } +} + +impl<'a, A, B> Deserialize<'a, (A, B)> for ZSerde +where + A: TryFrom, + >::Error: Debug, + B: TryFrom, + >::Error: Debug, +{ + type Error = ZError; + + fn deserialize(self, payload: &'a Payload) -> Result<(A, B), Self::Error> { + let codec = Zenoh080::new(); + let mut reader = payload.0.reader(); + + let abuf: ZBuf = codec.read(&mut reader).map_err(|e| zerror!("{:?}", e))?; + let apld = Payload::new(abuf); + + let bbuf: ZBuf = codec.read(&mut reader).map_err(|e| zerror!("{:?}", e))?; + let bpld = Payload::new(bbuf); + + let a = A::try_from(apld).map_err(|e| zerror!("{:?}", e))?; + let b = B::try_from(bpld).map_err(|e| zerror!("{:?}", e))?; + Ok((a, b)) } } +// Iterator +// impl Serialize for ZSerde +// where +// I: Iterator, +// T: Into, +// { +// type Output = Payload; + +// fn serialize(self, iter: I) -> Self::Output { +// let codec = Zenoh080::new(); +// let mut buffer: ZBuf = ZBuf::empty(); +// let mut writer = buffer.writer(); +// for t in iter { +// let tpld: Payload = t.into(); +// // SAFETY: we are serializing slices on a ZBuf, so serialization will never +// // fail unless we run out of memory. In that case, Rust memory allocator +// // will panic before the serializer has any chance to fail. +// unsafe { +// codec.write(&mut writer, &tpld.0).unwrap_unchecked(); +// } +// } + +// Payload::new(buffer) +// } +// } + // For convenience to always convert a Value the examples #[derive(Debug, Clone, PartialEq, Eq)] pub enum StringOrBase64 { @@ -619,14 +894,18 @@ mod tests { ($t:ty, $in:expr) => { let i = $in; let t = i.clone(); + println!("Serialize:\t{:?}", t); let v = Payload::serialize(t); + println!("Deserialize:\t{:?}", v); let o: $t = v.deserialize().unwrap(); - assert_eq!(i, o) + assert_eq!(i, o); + println!(""); }; } let mut rng = rand::thread_rng(); + // unsigned integer serialize_deserialize!(u8, u8::MIN); serialize_deserialize!(u16, u16::MIN); serialize_deserialize!(u32, u32::MIN); @@ -647,6 +926,7 @@ mod tests { serialize_deserialize!(usize, rng.gen::()); } + // signed integer serialize_deserialize!(i8, i8::MIN); serialize_deserialize!(i16, i16::MIN); serialize_deserialize!(i32, i32::MIN); @@ -667,6 +947,7 @@ mod tests { serialize_deserialize!(isize, rng.gen::()); } + // float serialize_deserialize!(f32, f32::MIN); serialize_deserialize!(f64, f64::MIN); @@ -678,13 +959,747 @@ mod tests { serialize_deserialize!(f64, rng.gen::()); } + // String serialize_deserialize!(String, ""); serialize_deserialize!(String, String::from("abcdefghijklmnopqrstuvwxyz")); + // Vec serialize_deserialize!(Vec, vec![0u8; 0]); serialize_deserialize!(Vec, vec![0u8; 64]); + // ZBuf serialize_deserialize!(ZBuf, ZBuf::from(vec![0u8; 0])); serialize_deserialize!(ZBuf, ZBuf::from(vec![0u8; 64])); + + // Tuple + serialize_deserialize!((usize, usize), (0, 1)); + serialize_deserialize!((usize, String), (0, String::from("a"))); + serialize_deserialize!((String, String), (String::from("a"), String::from("b"))); + + // Iterator + // let mut hm = Vec::new(); + // hm.push(0); + // hm.push(1); + // Payload::serialize(hm.iter()); + + // let mut hm = HashMap::new(); + // hm.insert(0, 0); + // hm.insert(1, 1); + // Payload::serialize(hm.iter().map(|(k, v)| (k, v))); + // for (k, v) in sample.payload().iter::<(String, serde_json::Value)>() {} } } + +// macro_rules! impl_iterator_inner { +// ($iter:expr) => {{ +// let codec = Zenoh080::new(); +// let mut buffer: ZBuf = ZBuf::empty(); +// let mut writer = buffer.writer(); +// for t in $iter { +// let tpld = ZSerde.serialize(t); +// // SAFETY: we are serializing slices on a ZBuf, so serialization will never +// // fail unless we run out of memory. In that case, Rust memory allocator +// // will panic before the serializer has any chance to fail. +// unsafe { +// codec.write(&mut writer, &tpld.0).unwrap_unchecked(); +// } +// } + +// Payload::new(buffer) +// }}; +// } + +// impl<'a> Serialize> for ZSerde { +// type Output = Payload; + +// fn serialize(self, iter: std::slice::Iter<'_, i32>) -> Self::Output { +// impl_iterator_inner!(iter) +// } +// } + +// impl<'a> Serialize> for ZSerde { +// type Output = Payload; + +// fn serialize(self, iter: std::slice::IterMut<'_, i32>) -> Self::Output { +// impl_iterator_inner!(iter) +// } +// } + +// impl Serialize<&mut dyn Iterator> for ZSerde { +// type Output = Payload; + +// fn serialize(self, iter: &mut dyn Iterator) -> Self::Output { +// let codec = Zenoh080::new(); +// let mut buffer: ZBuf = ZBuf::empty(); +// let mut writer = buffer.writer(); +// for t in iter { +// let tpld = ZSerde.serialize(t); +// // SAFETY: we are serializing slices on a ZBuf, so serialization will never +// // fail unless we run out of memory. In that case, Rust memory allocator +// // will panic before the serializer has any chance to fail. +// unsafe { +// codec.write(&mut writer, &tpld.0).unwrap_unchecked(); +// } +// } + +// Payload::new(buffer) +// } +// } + +// impl Serialize<(A, B)> for ZSerde +// where +// ZSerde: Serialize, +// ZSerde: Serialize, +// { +// type Output = Payload; + +// fn serialize(self, t: (A, B)) -> Self::Output { +// let (a, b) = t; + +// let codec = Zenoh080::new(); +// let mut buffer: ZBuf = ZBuf::empty(); +// let mut writer = buffer.writer(); +// let apld = Payload::serialize::(a); +// let bpld = Payload::serialize::(b); + +// // SAFETY: we are serializing slices on a ZBuf, so serialization will never +// // fail unless we run out of memory. In that case, Rust memory allocator +// // will panic before the serializer has any chance to fail. +// unsafe { +// codec.write(&mut writer, &apld.0).unwrap_unchecked(); +// codec.write(&mut writer, &bpld.0).unwrap_unchecked(); +// } + +// Payload::new(buffer) +// } +// } + +// impl<'a, A, B> Deserialize<'a, (A, B)> for ZSerde +// where +// A: TryFrom, +// ZSerde: Deserialize<'a, A>, +// >::Error: Debug, +// B: TryFrom, +// ZSerde: Deserialize<'a, B>, +// >::Error: Debug, +// { +// type Error = ZError; + +// fn deserialize(self, payload: &'a Payload) -> Result<(A, B), Self::Error> { +// let codec = Zenoh080::new(); +// let mut reader = payload.0.reader(); + +// let abuf: ZBuf = codec.read(&mut reader).map_err(|e| zerror!("{:?}", e))?; +// let apld = Payload::new(abuf); + +// let bbuf: ZBuf = codec.read(&mut reader).map_err(|e| zerror!("{:?}", e))?; +// let bpld = Payload::new(bbuf); + +// let a = A::try_from(apld).map_err(|e| zerror!("{:?}", e))?; +// let b = B::try_from(bpld).map_err(|e| zerror!("{:?}", e))?; +// Ok((a, b)) +// } +// } + +// impl Serialize<&mut dyn Iterator> for ZSerde +// where +// ZSerde: Serialize, +// { +// type Output = Payload; + +// fn serialize(self, iter: &mut dyn Iterator) -> Self::Output { +// let codec = Zenoh080::new(); +// let mut buffer: ZBuf = ZBuf::empty(); +// let mut writer = buffer.writer(); +// for t in iter { +// let tpld = ZSerde.serialize(t); +// // SAFETY: we are serializing slices on a ZBuf, so serialization will never +// // fail unless we run out of memory. In that case, Rust memory allocator +// // will panic before the serializer has any chance to fail. +// unsafe { +// codec.write(&mut writer, &tpld.0).unwrap_unchecked(); +// } +// } + +// Payload::new(buffer) +// } +// } + +// Iterator +// macro_rules! impl_iterator_serialize { +// ($a:ty) => { +// impl Serialize<&mut dyn Iterator> for ZSerde +// { +// type Output = Payload; + +// fn serialize(self, iter: &mut dyn Iterator) -> Self::Output { +// let codec = Zenoh080::new(); +// let mut buffer: ZBuf = ZBuf::empty(); +// let mut writer = buffer.writer(); +// for t in iter { +// let tpld = ZSerde.serialize(t); +// // SAFETY: we are serializing slices on a ZBuf, so serialization will never +// // fail unless we run out of memory. In that case, Rust memory allocator +// // will panic before the serializer has any chance to fail. +// unsafe { +// codec.write(&mut writer, &tpld.0).unwrap_unchecked(); +// } +// } + +// Payload::new(buffer) +// } +// } +// }; +// } + +// Tuples +// macro_rules! impl_tuple_serialize { +// ($a:ty, $b:ty) => { +// impl Serialize<($a, $b)> for ZSerde +// { +// type Output = Payload; + +// fn serialize(self, t: ($a, $b)) -> Self::Output { +// let (a, b) = t; + +// let codec = Zenoh080::new(); +// let mut buffer: ZBuf = ZBuf::empty(); +// let mut writer = buffer.writer(); +// let apld = Payload::serialize::<$a>(a); +// let bpld = Payload::serialize::<$b>(b); + +// // SAFETY: we are serializing slices on a ZBuf, so serialization will never +// // fail unless we run out of memory. In that case, Rust memory allocator +// // will panic before the serializer has any chance to fail. +// unsafe { +// codec.write(&mut writer, &apld.0).unwrap_unchecked(); +// codec.write(&mut writer, &bpld.0).unwrap_unchecked(); +// } + +// Payload::new(buffer) +// } +// } +// } + +// } + +// macro_rules! impl_tuple_deserialize { +// ($a:ty, $b:ty) => { +// impl<'a> Deserialize<'a, ($a, $b)> for ZSerde { +// type Error = ZError; + +// fn deserialize(self, payload: &'a Payload) -> Result<($a, $b), Self::Error> { +// let codec = Zenoh080::new(); +// let mut reader = payload.0.reader(); + +// let abuf: ZBuf = codec.read(&mut reader).map_err(|e| zerror!("{:?}", e))?; +// let apld = Payload::new(abuf); + +// let bbuf: ZBuf = codec.read(&mut reader).map_err(|e| zerror!("{:?}", e))?; +// let bpld = Payload::new(bbuf); + +// let a = apld.deserialize::<$a>().map_err(|e| zerror!("{:?}", e))?; +// let b = bpld.deserialize::<$b>().map_err(|e| zerror!("{:?}", e))?; +// Ok((a, b)) +// } +// } +// }; +// } + +// impl_tuple_serialize!(u8, u8); +// impl_tuple_deserialize!(u8, u8); +// impl_tuple_serialize!(u8, u16); +// impl_tuple_deserialize!(u8, u16); +// impl_tuple_serialize!(u8, u32); +// impl_tuple_deserialize!(u8, u32); +// impl_tuple_serialize!(u8, u64); +// impl_tuple_deserialize!(u8, u64); +// impl_tuple_serialize!(u8, usize); +// impl_tuple_deserialize!(u8, usize); +// impl_tuple_serialize!(u8, i8); +// impl_tuple_deserialize!(u8, i8); +// impl_tuple_serialize!(u8, i16); +// impl_tuple_deserialize!(u8, i16); +// impl_tuple_serialize!(u8, i32); +// impl_tuple_deserialize!(u8, i32); +// impl_tuple_serialize!(u8, isize); +// impl_tuple_deserialize!(u8, isize); +// impl_tuple_serialize!(u8, f32); +// impl_tuple_deserialize!(u8, f32); +// impl_tuple_serialize!(u8, f64); +// impl_tuple_deserialize!(u8, f64); +// impl_tuple_serialize!(u8, bool); +// impl_tuple_deserialize!(u8, bool); +// impl_tuple_serialize!(u8, ZBuf); +// impl_tuple_deserialize!(u8, ZBuf); +// impl_tuple_serialize!(u8, Vec); +// impl_tuple_deserialize!(u8, Vec); +// impl_tuple_serialize!(u8, String); +// impl_tuple_deserialize!(u8, String); +// impl_tuple_serialize!(u8, &[u8]); +// impl_tuple_serialize!(u16, u8); +// impl_tuple_deserialize!(u16, u8); +// impl_tuple_serialize!(u16, u16); +// impl_tuple_deserialize!(u16, u16); +// impl_tuple_serialize!(u16, u32); +// impl_tuple_deserialize!(u16, u32); +// impl_tuple_serialize!(u16, u64); +// impl_tuple_deserialize!(u16, u64); +// impl_tuple_serialize!(u16, usize); +// impl_tuple_deserialize!(u16, usize); +// impl_tuple_serialize!(u16, i8); +// impl_tuple_deserialize!(u16, i8); +// impl_tuple_serialize!(u16, i16); +// impl_tuple_deserialize!(u16, i16); +// impl_tuple_serialize!(u16, i32); +// impl_tuple_deserialize!(u16, i32); +// impl_tuple_serialize!(u16, isize); +// impl_tuple_deserialize!(u16, isize); +// impl_tuple_serialize!(u16, f32); +// impl_tuple_deserialize!(u16, f32); +// impl_tuple_serialize!(u16, f64); +// impl_tuple_deserialize!(u16, f64); +// impl_tuple_serialize!(u16, bool); +// impl_tuple_deserialize!(u16, bool); +// impl_tuple_serialize!(u16, ZBuf); +// impl_tuple_deserialize!(u16, ZBuf); +// impl_tuple_serialize!(u16, Vec); +// impl_tuple_deserialize!(u16, Vec); +// impl_tuple_serialize!(u16, String); +// impl_tuple_deserialize!(u16, String); +// impl_tuple_serialize!(u16, &[u8]); +// impl_tuple_serialize!(u32, u8); +// impl_tuple_deserialize!(u32, u8); +// impl_tuple_serialize!(u32, u16); +// impl_tuple_deserialize!(u32, u16); +// impl_tuple_serialize!(u32, u32); +// impl_tuple_deserialize!(u32, u32); +// impl_tuple_serialize!(u32, u64); +// impl_tuple_deserialize!(u32, u64); +// impl_tuple_serialize!(u32, usize); +// impl_tuple_deserialize!(u32, usize); +// impl_tuple_serialize!(u32, i8); +// impl_tuple_deserialize!(u32, i8); +// impl_tuple_serialize!(u32, i16); +// impl_tuple_deserialize!(u32, i16); +// impl_tuple_serialize!(u32, i32); +// impl_tuple_deserialize!(u32, i32); +// impl_tuple_serialize!(u32, isize); +// impl_tuple_deserialize!(u32, isize); +// impl_tuple_serialize!(u32, f32); +// impl_tuple_deserialize!(u32, f32); +// impl_tuple_serialize!(u32, f64); +// impl_tuple_deserialize!(u32, f64); +// impl_tuple_serialize!(u32, bool); +// impl_tuple_deserialize!(u32, bool); +// impl_tuple_serialize!(u32, ZBuf); +// impl_tuple_deserialize!(u32, ZBuf); +// impl_tuple_serialize!(u32, Vec); +// impl_tuple_deserialize!(u32, Vec); +// impl_tuple_serialize!(u32, String); +// impl_tuple_deserialize!(u32, String); +// impl_tuple_serialize!(u32, &[u8]); +// impl_tuple_serialize!(u64, u8); +// impl_tuple_deserialize!(u64, u8); +// impl_tuple_serialize!(u64, u16); +// impl_tuple_deserialize!(u64, u16); +// impl_tuple_serialize!(u64, u32); +// impl_tuple_deserialize!(u64, u32); +// impl_tuple_serialize!(u64, u64); +// impl_tuple_deserialize!(u64, u64); +// impl_tuple_serialize!(u64, usize); +// impl_tuple_deserialize!(u64, usize); +// impl_tuple_serialize!(u64, i8); +// impl_tuple_deserialize!(u64, i8); +// impl_tuple_serialize!(u64, i16); +// impl_tuple_deserialize!(u64, i16); +// impl_tuple_serialize!(u64, i32); +// impl_tuple_deserialize!(u64, i32); +// impl_tuple_serialize!(u64, isize); +// impl_tuple_deserialize!(u64, isize); +// impl_tuple_serialize!(u64, f32); +// impl_tuple_deserialize!(u64, f32); +// impl_tuple_serialize!(u64, f64); +// impl_tuple_deserialize!(u64, f64); +// impl_tuple_serialize!(u64, bool); +// impl_tuple_deserialize!(u64, bool); +// impl_tuple_serialize!(u64, ZBuf); +// impl_tuple_deserialize!(u64, ZBuf); +// impl_tuple_serialize!(u64, Vec); +// impl_tuple_deserialize!(u64, Vec); +// impl_tuple_serialize!(u64, String); +// impl_tuple_deserialize!(u64, String); +// impl_tuple_serialize!(u64, &[u8]); +// impl_tuple_serialize!(usize, u8); +// impl_tuple_deserialize!(usize, u8); +// impl_tuple_serialize!(usize, u16); +// impl_tuple_deserialize!(usize, u16); +// impl_tuple_serialize!(usize, u32); +// impl_tuple_deserialize!(usize, u32); +// impl_tuple_serialize!(usize, u64); +// impl_tuple_deserialize!(usize, u64); +// impl_tuple_serialize!(usize, usize); +// impl_tuple_deserialize!(usize, usize); +// impl_tuple_serialize!(usize, i8); +// impl_tuple_deserialize!(usize, i8); +// impl_tuple_serialize!(usize, i16); +// impl_tuple_deserialize!(usize, i16); +// impl_tuple_serialize!(usize, i32); +// impl_tuple_deserialize!(usize, i32); +// impl_tuple_serialize!(usize, isize); +// impl_tuple_deserialize!(usize, isize); +// impl_tuple_serialize!(usize, f32); +// impl_tuple_deserialize!(usize, f32); +// impl_tuple_serialize!(usize, f64); +// impl_tuple_deserialize!(usize, f64); +// impl_tuple_serialize!(usize, bool); +// impl_tuple_deserialize!(usize, bool); +// impl_tuple_serialize!(usize, ZBuf); +// impl_tuple_deserialize!(usize, ZBuf); +// impl_tuple_serialize!(usize, Vec); +// impl_tuple_deserialize!(usize, Vec); +// impl_tuple_serialize!(usize, String); +// impl_tuple_deserialize!(usize, String); +// impl_tuple_serialize!(usize, &[u8]); +// impl_tuple_serialize!(i8, u8); +// impl_tuple_deserialize!(i8, u8); +// impl_tuple_serialize!(i8, u16); +// impl_tuple_deserialize!(i8, u16); +// impl_tuple_serialize!(i8, u32); +// impl_tuple_deserialize!(i8, u32); +// impl_tuple_serialize!(i8, u64); +// impl_tuple_deserialize!(i8, u64); +// impl_tuple_serialize!(i8, usize); +// impl_tuple_deserialize!(i8, usize); +// impl_tuple_serialize!(i8, i8); +// impl_tuple_deserialize!(i8, i8); +// impl_tuple_serialize!(i8, i16); +// impl_tuple_deserialize!(i8, i16); +// impl_tuple_serialize!(i8, i32); +// impl_tuple_deserialize!(i8, i32); +// impl_tuple_serialize!(i8, isize); +// impl_tuple_deserialize!(i8, isize); +// impl_tuple_serialize!(i8, f32); +// impl_tuple_deserialize!(i8, f32); +// impl_tuple_serialize!(i8, f64); +// impl_tuple_deserialize!(i8, f64); +// impl_tuple_serialize!(i8, bool); +// impl_tuple_deserialize!(i8, bool); +// impl_tuple_serialize!(i8, ZBuf); +// impl_tuple_deserialize!(i8, ZBuf); +// impl_tuple_serialize!(i8, Vec); +// impl_tuple_deserialize!(i8, Vec); +// impl_tuple_serialize!(i8, String); +// impl_tuple_deserialize!(i8, String); +// impl_tuple_serialize!(i8, &[u8]); +// impl_tuple_serialize!(i16, u8); +// impl_tuple_deserialize!(i16, u8); +// impl_tuple_serialize!(i16, u16); +// impl_tuple_deserialize!(i16, u16); +// impl_tuple_serialize!(i16, u32); +// impl_tuple_deserialize!(i16, u32); +// impl_tuple_serialize!(i16, u64); +// impl_tuple_deserialize!(i16, u64); +// impl_tuple_serialize!(i16, usize); +// impl_tuple_deserialize!(i16, usize); +// impl_tuple_serialize!(i16, i8); +// impl_tuple_deserialize!(i16, i8); +// impl_tuple_serialize!(i16, i16); +// impl_tuple_deserialize!(i16, i16); +// impl_tuple_serialize!(i16, i32); +// impl_tuple_deserialize!(i16, i32); +// impl_tuple_serialize!(i16, isize); +// impl_tuple_deserialize!(i16, isize); +// impl_tuple_serialize!(i16, f32); +// impl_tuple_deserialize!(i16, f32); +// impl_tuple_serialize!(i16, f64); +// impl_tuple_deserialize!(i16, f64); +// impl_tuple_serialize!(i16, bool); +// impl_tuple_deserialize!(i16, bool); +// impl_tuple_serialize!(i16, ZBuf); +// impl_tuple_deserialize!(i16, ZBuf); +// impl_tuple_serialize!(i16, Vec); +// impl_tuple_deserialize!(i16, Vec); +// impl_tuple_serialize!(i16, String); +// impl_tuple_deserialize!(i16, String); +// impl_tuple_serialize!(i16, &[u8]); +// impl_tuple_serialize!(i32, u8); +// impl_tuple_deserialize!(i32, u8); +// impl_tuple_serialize!(i32, u16); +// impl_tuple_deserialize!(i32, u16); +// impl_tuple_serialize!(i32, u32); +// impl_tuple_deserialize!(i32, u32); +// impl_tuple_serialize!(i32, u64); +// impl_tuple_deserialize!(i32, u64); +// impl_tuple_serialize!(i32, usize); +// impl_tuple_deserialize!(i32, usize); +// impl_tuple_serialize!(i32, i8); +// impl_tuple_deserialize!(i32, i8); +// impl_tuple_serialize!(i32, i16); +// impl_tuple_deserialize!(i32, i16); +// impl_tuple_serialize!(i32, i32); +// impl_tuple_deserialize!(i32, i32); +// impl_tuple_serialize!(i32, isize); +// impl_tuple_deserialize!(i32, isize); +// impl_tuple_serialize!(i32, f32); +// impl_tuple_deserialize!(i32, f32); +// impl_tuple_serialize!(i32, f64); +// impl_tuple_deserialize!(i32, f64); +// impl_tuple_serialize!(i32, bool); +// impl_tuple_deserialize!(i32, bool); +// impl_tuple_serialize!(i32, ZBuf); +// impl_tuple_deserialize!(i32, ZBuf); +// impl_tuple_serialize!(i32, Vec); +// impl_tuple_deserialize!(i32, Vec); +// impl_tuple_serialize!(i32, String); +// impl_tuple_deserialize!(i32, String); +// impl_tuple_serialize!(i32, &[u8]); +// impl_tuple_serialize!(isize, u8); +// impl_tuple_deserialize!(isize, u8); +// impl_tuple_serialize!(isize, u16); +// impl_tuple_deserialize!(isize, u16); +// impl_tuple_serialize!(isize, u32); +// impl_tuple_deserialize!(isize, u32); +// impl_tuple_serialize!(isize, u64); +// impl_tuple_deserialize!(isize, u64); +// impl_tuple_serialize!(isize, usize); +// impl_tuple_deserialize!(isize, usize); +// impl_tuple_serialize!(isize, i8); +// impl_tuple_deserialize!(isize, i8); +// impl_tuple_serialize!(isize, i16); +// impl_tuple_deserialize!(isize, i16); +// impl_tuple_serialize!(isize, i32); +// impl_tuple_deserialize!(isize, i32); +// impl_tuple_serialize!(isize, isize); +// impl_tuple_deserialize!(isize, isize); +// impl_tuple_serialize!(isize, f32); +// impl_tuple_deserialize!(isize, f32); +// impl_tuple_serialize!(isize, f64); +// impl_tuple_deserialize!(isize, f64); +// impl_tuple_serialize!(isize, bool); +// impl_tuple_deserialize!(isize, bool); +// impl_tuple_serialize!(isize, ZBuf); +// impl_tuple_deserialize!(isize, ZBuf); +// impl_tuple_serialize!(isize, Vec); +// impl_tuple_deserialize!(isize, Vec); +// impl_tuple_serialize!(isize, String); +// impl_tuple_deserialize!(isize, String); +// impl_tuple_serialize!(isize, &[u8]); +// impl_tuple_serialize!(f32, u8); +// impl_tuple_deserialize!(f32, u8); +// impl_tuple_serialize!(f32, u16); +// impl_tuple_deserialize!(f32, u16); +// impl_tuple_serialize!(f32, u32); +// impl_tuple_deserialize!(f32, u32); +// impl_tuple_serialize!(f32, u64); +// impl_tuple_deserialize!(f32, u64); +// impl_tuple_serialize!(f32, usize); +// impl_tuple_deserialize!(f32, usize); +// impl_tuple_serialize!(f32, i8); +// impl_tuple_deserialize!(f32, i8); +// impl_tuple_serialize!(f32, i16); +// impl_tuple_deserialize!(f32, i16); +// impl_tuple_serialize!(f32, i32); +// impl_tuple_deserialize!(f32, i32); +// impl_tuple_serialize!(f32, isize); +// impl_tuple_deserialize!(f32, isize); +// impl_tuple_serialize!(f32, f32); +// impl_tuple_deserialize!(f32, f32); +// impl_tuple_serialize!(f32, f64); +// impl_tuple_deserialize!(f32, f64); +// impl_tuple_serialize!(f32, bool); +// impl_tuple_deserialize!(f32, bool); +// impl_tuple_serialize!(f32, ZBuf); +// impl_tuple_deserialize!(f32, ZBuf); +// impl_tuple_serialize!(f32, Vec); +// impl_tuple_deserialize!(f32, Vec); +// impl_tuple_serialize!(f32, String); +// impl_tuple_deserialize!(f32, String); +// impl_tuple_serialize!(f32, &[u8]); +// impl_tuple_serialize!(f64, u8); +// impl_tuple_deserialize!(f64, u8); +// impl_tuple_serialize!(f64, u16); +// impl_tuple_deserialize!(f64, u16); +// impl_tuple_serialize!(f64, u32); +// impl_tuple_deserialize!(f64, u32); +// impl_tuple_serialize!(f64, u64); +// impl_tuple_deserialize!(f64, u64); +// impl_tuple_serialize!(f64, usize); +// impl_tuple_deserialize!(f64, usize); +// impl_tuple_serialize!(f64, i8); +// impl_tuple_deserialize!(f64, i8); +// impl_tuple_serialize!(f64, i16); +// impl_tuple_deserialize!(f64, i16); +// impl_tuple_serialize!(f64, i32); +// impl_tuple_deserialize!(f64, i32); +// impl_tuple_serialize!(f64, isize); +// impl_tuple_deserialize!(f64, isize); +// impl_tuple_serialize!(f64, f32); +// impl_tuple_deserialize!(f64, f32); +// impl_tuple_serialize!(f64, f64); +// impl_tuple_deserialize!(f64, f64); +// impl_tuple_serialize!(f64, bool); +// impl_tuple_deserialize!(f64, bool); +// impl_tuple_serialize!(f64, ZBuf); +// impl_tuple_deserialize!(f64, ZBuf); +// impl_tuple_serialize!(f64, Vec); +// impl_tuple_deserialize!(f64, Vec); +// impl_tuple_serialize!(f64, String); +// impl_tuple_deserialize!(f64, String); +// impl_tuple_serialize!(f64, &[u8]); +// impl_tuple_serialize!(bool, u8); +// impl_tuple_deserialize!(bool, u8); +// impl_tuple_serialize!(bool, u16); +// impl_tuple_deserialize!(bool, u16); +// impl_tuple_serialize!(bool, u32); +// impl_tuple_deserialize!(bool, u32); +// impl_tuple_serialize!(bool, u64); +// impl_tuple_deserialize!(bool, u64); +// impl_tuple_serialize!(bool, usize); +// impl_tuple_deserialize!(bool, usize); +// impl_tuple_serialize!(bool, i8); +// impl_tuple_deserialize!(bool, i8); +// impl_tuple_serialize!(bool, i16); +// impl_tuple_deserialize!(bool, i16); +// impl_tuple_serialize!(bool, i32); +// impl_tuple_deserialize!(bool, i32); +// impl_tuple_serialize!(bool, isize); +// impl_tuple_deserialize!(bool, isize); +// impl_tuple_serialize!(bool, f32); +// impl_tuple_deserialize!(bool, f32); +// impl_tuple_serialize!(bool, f64); +// impl_tuple_deserialize!(bool, f64); +// impl_tuple_serialize!(bool, bool); +// impl_tuple_deserialize!(bool, bool); +// impl_tuple_serialize!(bool, ZBuf); +// impl_tuple_deserialize!(bool, ZBuf); +// impl_tuple_serialize!(bool, Vec); +// impl_tuple_deserialize!(bool, Vec); +// impl_tuple_serialize!(bool, String); +// impl_tuple_deserialize!(bool, String); +// impl_tuple_serialize!(bool, &[u8]); +// impl_tuple_serialize!(ZBuf, u8); +// impl_tuple_deserialize!(ZBuf, u8); +// impl_tuple_serialize!(ZBuf, u16); +// impl_tuple_deserialize!(ZBuf, u16); +// impl_tuple_serialize!(ZBuf, u32); +// impl_tuple_deserialize!(ZBuf, u32); +// impl_tuple_serialize!(ZBuf, u64); +// impl_tuple_deserialize!(ZBuf, u64); +// impl_tuple_serialize!(ZBuf, usize); +// impl_tuple_deserialize!(ZBuf, usize); +// impl_tuple_serialize!(ZBuf, i8); +// impl_tuple_deserialize!(ZBuf, i8); +// impl_tuple_serialize!(ZBuf, i16); +// impl_tuple_deserialize!(ZBuf, i16); +// impl_tuple_serialize!(ZBuf, i32); +// impl_tuple_deserialize!(ZBuf, i32); +// impl_tuple_serialize!(ZBuf, isize); +// impl_tuple_deserialize!(ZBuf, isize); +// impl_tuple_serialize!(ZBuf, f32); +// impl_tuple_deserialize!(ZBuf, f32); +// impl_tuple_serialize!(ZBuf, f64); +// impl_tuple_deserialize!(ZBuf, f64); +// impl_tuple_serialize!(ZBuf, bool); +// impl_tuple_deserialize!(ZBuf, bool); +// impl_tuple_serialize!(ZBuf, ZBuf); +// impl_tuple_deserialize!(ZBuf, ZBuf); +// impl_tuple_serialize!(ZBuf, Vec); +// impl_tuple_deserialize!(ZBuf, Vec); +// impl_tuple_serialize!(ZBuf, String); +// impl_tuple_deserialize!(ZBuf, String); +// impl_tuple_serialize!(ZBuf, &[u8]); +// impl_tuple_serialize!(Vec, u8); +// impl_tuple_deserialize!(Vec, u8); +// impl_tuple_serialize!(Vec, u16); +// impl_tuple_deserialize!(Vec, u16); +// impl_tuple_serialize!(Vec, u32); +// impl_tuple_deserialize!(Vec, u32); +// impl_tuple_serialize!(Vec, u64); +// impl_tuple_deserialize!(Vec, u64); +// impl_tuple_serialize!(Vec, usize); +// impl_tuple_deserialize!(Vec, usize); +// impl_tuple_serialize!(Vec, i8); +// impl_tuple_deserialize!(Vec, i8); +// impl_tuple_serialize!(Vec, i16); +// impl_tuple_deserialize!(Vec, i16); +// impl_tuple_serialize!(Vec, i32); +// impl_tuple_deserialize!(Vec, i32); +// impl_tuple_serialize!(Vec, isize); +// impl_tuple_deserialize!(Vec, isize); +// impl_tuple_serialize!(Vec, f32); +// impl_tuple_deserialize!(Vec, f32); +// impl_tuple_serialize!(Vec, f64); +// impl_tuple_deserialize!(Vec, f64); +// impl_tuple_serialize!(Vec, bool); +// impl_tuple_deserialize!(Vec, bool); +// impl_tuple_serialize!(Vec, ZBuf); +// impl_tuple_deserialize!(Vec, ZBuf); +// impl_tuple_serialize!(Vec, Vec); +// impl_tuple_deserialize!(Vec, Vec); +// impl_tuple_serialize!(Vec, String); +// impl_tuple_deserialize!(Vec, String); +// impl_tuple_serialize!(Vec, &[u8]); +// impl_tuple_serialize!(String, u8); +// impl_tuple_deserialize!(String, u8); +// impl_tuple_serialize!(String, u16); +// impl_tuple_deserialize!(String, u16); +// impl_tuple_serialize!(String, u32); +// impl_tuple_deserialize!(String, u32); +// impl_tuple_serialize!(String, u64); +// impl_tuple_deserialize!(String, u64); +// impl_tuple_serialize!(String, usize); +// impl_tuple_deserialize!(String, usize); +// impl_tuple_serialize!(String, i8); +// impl_tuple_deserialize!(String, i8); +// impl_tuple_serialize!(String, i16); +// impl_tuple_deserialize!(String, i16); +// impl_tuple_serialize!(String, i32); +// impl_tuple_deserialize!(String, i32); +// impl_tuple_serialize!(String, isize); +// impl_tuple_deserialize!(String, isize); +// impl_tuple_serialize!(String, f32); +// impl_tuple_deserialize!(String, f32); +// impl_tuple_serialize!(String, f64); +// impl_tuple_deserialize!(String, f64); +// impl_tuple_serialize!(String, bool); +// impl_tuple_deserialize!(String, bool); +// impl_tuple_serialize!(String, ZBuf); +// impl_tuple_deserialize!(String, ZBuf); +// impl_tuple_serialize!(String, Vec); +// impl_tuple_deserialize!(String, Vec); +// impl_tuple_serialize!(String, String); +// impl_tuple_deserialize!(String, String); +// impl_tuple_serialize!(String, &[u8]); +// impl_tuple_serialize!(&[u8], u8); +// impl_tuple_serialize!(&[u8], u16); +// impl_tuple_serialize!(&[u8], u32); +// impl_tuple_serialize!(&[u8], u64); +// impl_tuple_serialize!(&[u8], usize); +// impl_tuple_serialize!(&[u8], i8); +// impl_tuple_serialize!(&[u8], i16); +// impl_tuple_serialize!(&[u8], i32); +// impl_tuple_serialize!(&[u8], isize); +// impl_tuple_serialize!(&[u8], f32); +// impl_tuple_serialize!(&[u8], f64); +// impl_tuple_serialize!(&[u8], bool); +// impl_tuple_serialize!(&[u8], ZBuf); +// impl_tuple_serialize!(&[u8], Vec); +// impl_tuple_serialize!(&[u8], String); +// impl_tuple_serialize!(&[u8], &[u8]); +// impl_iterator_serialize!(u8); +// impl_iterator_serialize!(u16); +// impl_iterator_serialize!(u32); +// impl_iterator_serialize!(u64); +// impl_iterator_serialize!(usize); +// impl_iterator_serialize!(i8); +// impl_iterator_serialize!(i16); +// impl_iterator_serialize!(i32); +// impl_iterator_serialize!(isize); +// impl_iterator_serialize!(f32); +// impl_iterator_serialize!(f64); +// impl_iterator_serialize!(bool); +// impl_iterator_serialize!(ZBuf); +// impl_iterator_serialize!(Vec); +// impl_iterator_serialize!(String); +// impl_iterator_serialize!(&[u8]); diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 58589bfe8f..ae9119ac8a 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -19,6 +19,7 @@ use crate::handlers::{locked, DefaultHandler}; use crate::net::primitives::Primitives; use crate::prelude::*; use crate::sample::QoS; +#[cfg(feature = "unstable")] use crate::sample::SourceInfo; use crate::Id; use crate::SessionRef; diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index 9bc6c9c331..0c1c193568 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -57,12 +57,7 @@ use zenoh_collections::SingleOrVec; use zenoh_config::unwrap_or_default; use zenoh_core::{zconfigurable, zread, Resolve, ResolveClosure, ResolveFuture, SyncResolve}; #[cfg(feature = "unstable")] -use zenoh_protocol::network::declare::SubscriberId; -use zenoh_protocol::network::AtomicRequestId; -use zenoh_protocol::network::RequestId; -use zenoh_protocol::zenoh::reply::ReplyBody; -use zenoh_protocol::zenoh::Del; -use zenoh_protocol::zenoh::Put; +use zenoh_protocol::network::{declare::SubscriberId, ext}; use zenoh_protocol::{ core::{ key_expr::{keyexpr, OwnedKeyExpr}, @@ -74,13 +69,13 @@ use zenoh_protocol::{ subscriber::ext::SubscriberInfo, Declare, DeclareBody, DeclareKeyExpr, DeclareMode, DeclareQueryable, DeclareSubscriber, UndeclareQueryable, UndeclareSubscriber, }, - ext, request::{self, ext::TargetType, Request}, - Mapping, Push, Response, ResponseFinal, + AtomicRequestId, Mapping, Push, RequestId, Response, ResponseFinal, }, zenoh::{ query::{self, ext::QueryBodyType, Consolidation}, - PushBody, RequestBody, ResponseBody, + reply::ReplyBody, + Del, PushBody, Put, RequestBody, ResponseBody, }, }; use zenoh_result::ZResult; diff --git a/zenoh/src/subscriber.rs b/zenoh/src/subscriber.rs index 60a31a6577..47d41ebb1f 100644 --- a/zenoh/src/subscriber.rs +++ b/zenoh/src/subscriber.rs @@ -202,9 +202,6 @@ pub struct SubscriberBuilder<'a, 'b, Handler> { #[cfg(not(feature = "unstable"))] pub(crate) reliability: Reliability, - #[cfg(not(feature = "unstable"))] - pub(crate) mode: Mode, - #[cfg(feature = "unstable")] pub origin: Locality, #[cfg(not(feature = "unstable"))] From 3dea601356c7fdb08f14c7ce6c94e732db5b1836 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Mon, 8 Apr 2024 18:33:22 +0200 Subject: [PATCH 02/19] Payload iter impl --- zenoh/src/payload.rs | 821 ++++--------------------------------------- 1 file changed, 67 insertions(+), 754 deletions(-) diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index db3126d93d..ed8c1b98c3 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -80,10 +80,11 @@ impl Payload { } /// Get a [`PayloadReader`] implementing [`std::io::Read`] trait. - pub fn iter(&self) -> PayloadIterator<'_, T> + pub fn iter<'a, T>(&'a self) -> PayloadIterator<'a, T> where T: TryFrom, - ZSerde: for<'b> Deserialize<'b, T, Error = ZDeserializeError>, + ZSerde: Deserialize<'a, T>, + >::Error: Debug, { PayloadIterator { reader: self.0.reader(), @@ -144,7 +145,8 @@ where impl<'a, T> Iterator for PayloadIterator<'a, T> where - ZSerde: for<'b> Deserialize<'b, T, Error = ZDeserializeError>, + ZSerde: for<'b> Deserialize<'b, T>, + >::Error: Debug, { type Item = T; @@ -164,6 +166,28 @@ where } } +impl FromIterator for Payload +where + ZSerde: Serialize, +{ + fn from_iter>(iter: T) -> Self { + let codec = Zenoh080::new(); + let mut buffer: ZBuf = ZBuf::empty(); + let mut writer = buffer.writer(); + for t in iter { + let tpld = ZSerde.serialize(t); + // SAFETY: we are serializing slices on a ZBuf, so serialization will never + // fail unless we run out of memory. In that case, Rust memory allocator + // will panic before the serializer has any chance to fail. + unsafe { + codec.write(&mut writer, &tpld.0).unwrap_unchecked(); + } + } + + Payload::new(buffer) + } +} + /// The default serializer for Zenoh payload. It supports primitives types, such as: vec, int, uint, float, string, bool. /// It also supports common Rust serde values. #[derive(Clone, Copy, Debug)] @@ -786,6 +810,16 @@ where } } +impl From<(A, B)> for Payload +where + A: Into, + B: Into, +{ + fn from(value: (A, B)) -> Self { + ZSerde.serialize(value) + } +} + impl<'a, A, B> Deserialize<'a, (A, B)> for ZSerde where A: TryFrom, @@ -811,31 +845,19 @@ where } } -// Iterator -// impl Serialize for ZSerde -// where -// I: Iterator, -// T: Into, -// { -// type Output = Payload; - -// fn serialize(self, iter: I) -> Self::Output { -// let codec = Zenoh080::new(); -// let mut buffer: ZBuf = ZBuf::empty(); -// let mut writer = buffer.writer(); -// for t in iter { -// let tpld: Payload = t.into(); -// // SAFETY: we are serializing slices on a ZBuf, so serialization will never -// // fail unless we run out of memory. In that case, Rust memory allocator -// // will panic before the serializer has any chance to fail. -// unsafe { -// codec.write(&mut writer, &tpld.0).unwrap_unchecked(); -// } -// } - -// Payload::new(buffer) -// } -// } +impl TryFrom for (A, B) +where + A: TryFrom, + >::Error: Debug, + B: TryFrom, + >::Error: Debug, +{ + type Error = ZError; + + fn try_from(value: Payload) -> Result { + ZSerde.deserialize(&value) + } +} // For convenience to always convert a Value the examples #[derive(Debug, Clone, PartialEq, Eq)] @@ -977,729 +999,20 @@ mod tests { serialize_deserialize!((String, String), (String::from("a"), String::from("b"))); // Iterator - // let mut hm = Vec::new(); - // hm.push(0); - // hm.push(1); - // Payload::serialize(hm.iter()); - - // let mut hm = HashMap::new(); - // hm.insert(0, 0); - // hm.insert(1, 1); - // Payload::serialize(hm.iter().map(|(k, v)| (k, v))); - // for (k, v) in sample.payload().iter::<(String, serde_json::Value)>() {} - } -} - -// macro_rules! impl_iterator_inner { -// ($iter:expr) => {{ -// let codec = Zenoh080::new(); -// let mut buffer: ZBuf = ZBuf::empty(); -// let mut writer = buffer.writer(); -// for t in $iter { -// let tpld = ZSerde.serialize(t); -// // SAFETY: we are serializing slices on a ZBuf, so serialization will never -// // fail unless we run out of memory. In that case, Rust memory allocator -// // will panic before the serializer has any chance to fail. -// unsafe { -// codec.write(&mut writer, &tpld.0).unwrap_unchecked(); -// } -// } - -// Payload::new(buffer) -// }}; -// } - -// impl<'a> Serialize> for ZSerde { -// type Output = Payload; - -// fn serialize(self, iter: std::slice::Iter<'_, i32>) -> Self::Output { -// impl_iterator_inner!(iter) -// } -// } - -// impl<'a> Serialize> for ZSerde { -// type Output = Payload; - -// fn serialize(self, iter: std::slice::IterMut<'_, i32>) -> Self::Output { -// impl_iterator_inner!(iter) -// } -// } - -// impl Serialize<&mut dyn Iterator> for ZSerde { -// type Output = Payload; - -// fn serialize(self, iter: &mut dyn Iterator) -> Self::Output { -// let codec = Zenoh080::new(); -// let mut buffer: ZBuf = ZBuf::empty(); -// let mut writer = buffer.writer(); -// for t in iter { -// let tpld = ZSerde.serialize(t); -// // SAFETY: we are serializing slices on a ZBuf, so serialization will never -// // fail unless we run out of memory. In that case, Rust memory allocator -// // will panic before the serializer has any chance to fail. -// unsafe { -// codec.write(&mut writer, &tpld.0).unwrap_unchecked(); -// } -// } - -// Payload::new(buffer) -// } -// } - -// impl Serialize<(A, B)> for ZSerde -// where -// ZSerde: Serialize, -// ZSerde: Serialize, -// { -// type Output = Payload; - -// fn serialize(self, t: (A, B)) -> Self::Output { -// let (a, b) = t; - -// let codec = Zenoh080::new(); -// let mut buffer: ZBuf = ZBuf::empty(); -// let mut writer = buffer.writer(); -// let apld = Payload::serialize::(a); -// let bpld = Payload::serialize::(b); - -// // SAFETY: we are serializing slices on a ZBuf, so serialization will never -// // fail unless we run out of memory. In that case, Rust memory allocator -// // will panic before the serializer has any chance to fail. -// unsafe { -// codec.write(&mut writer, &apld.0).unwrap_unchecked(); -// codec.write(&mut writer, &bpld.0).unwrap_unchecked(); -// } - -// Payload::new(buffer) -// } -// } - -// impl<'a, A, B> Deserialize<'a, (A, B)> for ZSerde -// where -// A: TryFrom, -// ZSerde: Deserialize<'a, A>, -// >::Error: Debug, -// B: TryFrom, -// ZSerde: Deserialize<'a, B>, -// >::Error: Debug, -// { -// type Error = ZError; - -// fn deserialize(self, payload: &'a Payload) -> Result<(A, B), Self::Error> { -// let codec = Zenoh080::new(); -// let mut reader = payload.0.reader(); - -// let abuf: ZBuf = codec.read(&mut reader).map_err(|e| zerror!("{:?}", e))?; -// let apld = Payload::new(abuf); - -// let bbuf: ZBuf = codec.read(&mut reader).map_err(|e| zerror!("{:?}", e))?; -// let bpld = Payload::new(bbuf); - -// let a = A::try_from(apld).map_err(|e| zerror!("{:?}", e))?; -// let b = B::try_from(bpld).map_err(|e| zerror!("{:?}", e))?; -// Ok((a, b)) -// } -// } - -// impl Serialize<&mut dyn Iterator> for ZSerde -// where -// ZSerde: Serialize, -// { -// type Output = Payload; - -// fn serialize(self, iter: &mut dyn Iterator) -> Self::Output { -// let codec = Zenoh080::new(); -// let mut buffer: ZBuf = ZBuf::empty(); -// let mut writer = buffer.writer(); -// for t in iter { -// let tpld = ZSerde.serialize(t); -// // SAFETY: we are serializing slices on a ZBuf, so serialization will never -// // fail unless we run out of memory. In that case, Rust memory allocator -// // will panic before the serializer has any chance to fail. -// unsafe { -// codec.write(&mut writer, &tpld.0).unwrap_unchecked(); -// } -// } - -// Payload::new(buffer) -// } -// } - -// Iterator -// macro_rules! impl_iterator_serialize { -// ($a:ty) => { -// impl Serialize<&mut dyn Iterator> for ZSerde -// { -// type Output = Payload; - -// fn serialize(self, iter: &mut dyn Iterator) -> Self::Output { -// let codec = Zenoh080::new(); -// let mut buffer: ZBuf = ZBuf::empty(); -// let mut writer = buffer.writer(); -// for t in iter { -// let tpld = ZSerde.serialize(t); -// // SAFETY: we are serializing slices on a ZBuf, so serialization will never -// // fail unless we run out of memory. In that case, Rust memory allocator -// // will panic before the serializer has any chance to fail. -// unsafe { -// codec.write(&mut writer, &tpld.0).unwrap_unchecked(); -// } -// } - -// Payload::new(buffer) -// } -// } -// }; -// } - -// Tuples -// macro_rules! impl_tuple_serialize { -// ($a:ty, $b:ty) => { -// impl Serialize<($a, $b)> for ZSerde -// { -// type Output = Payload; - -// fn serialize(self, t: ($a, $b)) -> Self::Output { -// let (a, b) = t; - -// let codec = Zenoh080::new(); -// let mut buffer: ZBuf = ZBuf::empty(); -// let mut writer = buffer.writer(); -// let apld = Payload::serialize::<$a>(a); -// let bpld = Payload::serialize::<$b>(b); - -// // SAFETY: we are serializing slices on a ZBuf, so serialization will never -// // fail unless we run out of memory. In that case, Rust memory allocator -// // will panic before the serializer has any chance to fail. -// unsafe { -// codec.write(&mut writer, &apld.0).unwrap_unchecked(); -// codec.write(&mut writer, &bpld.0).unwrap_unchecked(); -// } - -// Payload::new(buffer) -// } -// } -// } - -// } - -// macro_rules! impl_tuple_deserialize { -// ($a:ty, $b:ty) => { -// impl<'a> Deserialize<'a, ($a, $b)> for ZSerde { -// type Error = ZError; - -// fn deserialize(self, payload: &'a Payload) -> Result<($a, $b), Self::Error> { -// let codec = Zenoh080::new(); -// let mut reader = payload.0.reader(); - -// let abuf: ZBuf = codec.read(&mut reader).map_err(|e| zerror!("{:?}", e))?; -// let apld = Payload::new(abuf); - -// let bbuf: ZBuf = codec.read(&mut reader).map_err(|e| zerror!("{:?}", e))?; -// let bpld = Payload::new(bbuf); - -// let a = apld.deserialize::<$a>().map_err(|e| zerror!("{:?}", e))?; -// let b = bpld.deserialize::<$b>().map_err(|e| zerror!("{:?}", e))?; -// Ok((a, b)) -// } -// } -// }; -// } - -// impl_tuple_serialize!(u8, u8); -// impl_tuple_deserialize!(u8, u8); -// impl_tuple_serialize!(u8, u16); -// impl_tuple_deserialize!(u8, u16); -// impl_tuple_serialize!(u8, u32); -// impl_tuple_deserialize!(u8, u32); -// impl_tuple_serialize!(u8, u64); -// impl_tuple_deserialize!(u8, u64); -// impl_tuple_serialize!(u8, usize); -// impl_tuple_deserialize!(u8, usize); -// impl_tuple_serialize!(u8, i8); -// impl_tuple_deserialize!(u8, i8); -// impl_tuple_serialize!(u8, i16); -// impl_tuple_deserialize!(u8, i16); -// impl_tuple_serialize!(u8, i32); -// impl_tuple_deserialize!(u8, i32); -// impl_tuple_serialize!(u8, isize); -// impl_tuple_deserialize!(u8, isize); -// impl_tuple_serialize!(u8, f32); -// impl_tuple_deserialize!(u8, f32); -// impl_tuple_serialize!(u8, f64); -// impl_tuple_deserialize!(u8, f64); -// impl_tuple_serialize!(u8, bool); -// impl_tuple_deserialize!(u8, bool); -// impl_tuple_serialize!(u8, ZBuf); -// impl_tuple_deserialize!(u8, ZBuf); -// impl_tuple_serialize!(u8, Vec); -// impl_tuple_deserialize!(u8, Vec); -// impl_tuple_serialize!(u8, String); -// impl_tuple_deserialize!(u8, String); -// impl_tuple_serialize!(u8, &[u8]); -// impl_tuple_serialize!(u16, u8); -// impl_tuple_deserialize!(u16, u8); -// impl_tuple_serialize!(u16, u16); -// impl_tuple_deserialize!(u16, u16); -// impl_tuple_serialize!(u16, u32); -// impl_tuple_deserialize!(u16, u32); -// impl_tuple_serialize!(u16, u64); -// impl_tuple_deserialize!(u16, u64); -// impl_tuple_serialize!(u16, usize); -// impl_tuple_deserialize!(u16, usize); -// impl_tuple_serialize!(u16, i8); -// impl_tuple_deserialize!(u16, i8); -// impl_tuple_serialize!(u16, i16); -// impl_tuple_deserialize!(u16, i16); -// impl_tuple_serialize!(u16, i32); -// impl_tuple_deserialize!(u16, i32); -// impl_tuple_serialize!(u16, isize); -// impl_tuple_deserialize!(u16, isize); -// impl_tuple_serialize!(u16, f32); -// impl_tuple_deserialize!(u16, f32); -// impl_tuple_serialize!(u16, f64); -// impl_tuple_deserialize!(u16, f64); -// impl_tuple_serialize!(u16, bool); -// impl_tuple_deserialize!(u16, bool); -// impl_tuple_serialize!(u16, ZBuf); -// impl_tuple_deserialize!(u16, ZBuf); -// impl_tuple_serialize!(u16, Vec); -// impl_tuple_deserialize!(u16, Vec); -// impl_tuple_serialize!(u16, String); -// impl_tuple_deserialize!(u16, String); -// impl_tuple_serialize!(u16, &[u8]); -// impl_tuple_serialize!(u32, u8); -// impl_tuple_deserialize!(u32, u8); -// impl_tuple_serialize!(u32, u16); -// impl_tuple_deserialize!(u32, u16); -// impl_tuple_serialize!(u32, u32); -// impl_tuple_deserialize!(u32, u32); -// impl_tuple_serialize!(u32, u64); -// impl_tuple_deserialize!(u32, u64); -// impl_tuple_serialize!(u32, usize); -// impl_tuple_deserialize!(u32, usize); -// impl_tuple_serialize!(u32, i8); -// impl_tuple_deserialize!(u32, i8); -// impl_tuple_serialize!(u32, i16); -// impl_tuple_deserialize!(u32, i16); -// impl_tuple_serialize!(u32, i32); -// impl_tuple_deserialize!(u32, i32); -// impl_tuple_serialize!(u32, isize); -// impl_tuple_deserialize!(u32, isize); -// impl_tuple_serialize!(u32, f32); -// impl_tuple_deserialize!(u32, f32); -// impl_tuple_serialize!(u32, f64); -// impl_tuple_deserialize!(u32, f64); -// impl_tuple_serialize!(u32, bool); -// impl_tuple_deserialize!(u32, bool); -// impl_tuple_serialize!(u32, ZBuf); -// impl_tuple_deserialize!(u32, ZBuf); -// impl_tuple_serialize!(u32, Vec); -// impl_tuple_deserialize!(u32, Vec); -// impl_tuple_serialize!(u32, String); -// impl_tuple_deserialize!(u32, String); -// impl_tuple_serialize!(u32, &[u8]); -// impl_tuple_serialize!(u64, u8); -// impl_tuple_deserialize!(u64, u8); -// impl_tuple_serialize!(u64, u16); -// impl_tuple_deserialize!(u64, u16); -// impl_tuple_serialize!(u64, u32); -// impl_tuple_deserialize!(u64, u32); -// impl_tuple_serialize!(u64, u64); -// impl_tuple_deserialize!(u64, u64); -// impl_tuple_serialize!(u64, usize); -// impl_tuple_deserialize!(u64, usize); -// impl_tuple_serialize!(u64, i8); -// impl_tuple_deserialize!(u64, i8); -// impl_tuple_serialize!(u64, i16); -// impl_tuple_deserialize!(u64, i16); -// impl_tuple_serialize!(u64, i32); -// impl_tuple_deserialize!(u64, i32); -// impl_tuple_serialize!(u64, isize); -// impl_tuple_deserialize!(u64, isize); -// impl_tuple_serialize!(u64, f32); -// impl_tuple_deserialize!(u64, f32); -// impl_tuple_serialize!(u64, f64); -// impl_tuple_deserialize!(u64, f64); -// impl_tuple_serialize!(u64, bool); -// impl_tuple_deserialize!(u64, bool); -// impl_tuple_serialize!(u64, ZBuf); -// impl_tuple_deserialize!(u64, ZBuf); -// impl_tuple_serialize!(u64, Vec); -// impl_tuple_deserialize!(u64, Vec); -// impl_tuple_serialize!(u64, String); -// impl_tuple_deserialize!(u64, String); -// impl_tuple_serialize!(u64, &[u8]); -// impl_tuple_serialize!(usize, u8); -// impl_tuple_deserialize!(usize, u8); -// impl_tuple_serialize!(usize, u16); -// impl_tuple_deserialize!(usize, u16); -// impl_tuple_serialize!(usize, u32); -// impl_tuple_deserialize!(usize, u32); -// impl_tuple_serialize!(usize, u64); -// impl_tuple_deserialize!(usize, u64); -// impl_tuple_serialize!(usize, usize); -// impl_tuple_deserialize!(usize, usize); -// impl_tuple_serialize!(usize, i8); -// impl_tuple_deserialize!(usize, i8); -// impl_tuple_serialize!(usize, i16); -// impl_tuple_deserialize!(usize, i16); -// impl_tuple_serialize!(usize, i32); -// impl_tuple_deserialize!(usize, i32); -// impl_tuple_serialize!(usize, isize); -// impl_tuple_deserialize!(usize, isize); -// impl_tuple_serialize!(usize, f32); -// impl_tuple_deserialize!(usize, f32); -// impl_tuple_serialize!(usize, f64); -// impl_tuple_deserialize!(usize, f64); -// impl_tuple_serialize!(usize, bool); -// impl_tuple_deserialize!(usize, bool); -// impl_tuple_serialize!(usize, ZBuf); -// impl_tuple_deserialize!(usize, ZBuf); -// impl_tuple_serialize!(usize, Vec); -// impl_tuple_deserialize!(usize, Vec); -// impl_tuple_serialize!(usize, String); -// impl_tuple_deserialize!(usize, String); -// impl_tuple_serialize!(usize, &[u8]); -// impl_tuple_serialize!(i8, u8); -// impl_tuple_deserialize!(i8, u8); -// impl_tuple_serialize!(i8, u16); -// impl_tuple_deserialize!(i8, u16); -// impl_tuple_serialize!(i8, u32); -// impl_tuple_deserialize!(i8, u32); -// impl_tuple_serialize!(i8, u64); -// impl_tuple_deserialize!(i8, u64); -// impl_tuple_serialize!(i8, usize); -// impl_tuple_deserialize!(i8, usize); -// impl_tuple_serialize!(i8, i8); -// impl_tuple_deserialize!(i8, i8); -// impl_tuple_serialize!(i8, i16); -// impl_tuple_deserialize!(i8, i16); -// impl_tuple_serialize!(i8, i32); -// impl_tuple_deserialize!(i8, i32); -// impl_tuple_serialize!(i8, isize); -// impl_tuple_deserialize!(i8, isize); -// impl_tuple_serialize!(i8, f32); -// impl_tuple_deserialize!(i8, f32); -// impl_tuple_serialize!(i8, f64); -// impl_tuple_deserialize!(i8, f64); -// impl_tuple_serialize!(i8, bool); -// impl_tuple_deserialize!(i8, bool); -// impl_tuple_serialize!(i8, ZBuf); -// impl_tuple_deserialize!(i8, ZBuf); -// impl_tuple_serialize!(i8, Vec); -// impl_tuple_deserialize!(i8, Vec); -// impl_tuple_serialize!(i8, String); -// impl_tuple_deserialize!(i8, String); -// impl_tuple_serialize!(i8, &[u8]); -// impl_tuple_serialize!(i16, u8); -// impl_tuple_deserialize!(i16, u8); -// impl_tuple_serialize!(i16, u16); -// impl_tuple_deserialize!(i16, u16); -// impl_tuple_serialize!(i16, u32); -// impl_tuple_deserialize!(i16, u32); -// impl_tuple_serialize!(i16, u64); -// impl_tuple_deserialize!(i16, u64); -// impl_tuple_serialize!(i16, usize); -// impl_tuple_deserialize!(i16, usize); -// impl_tuple_serialize!(i16, i8); -// impl_tuple_deserialize!(i16, i8); -// impl_tuple_serialize!(i16, i16); -// impl_tuple_deserialize!(i16, i16); -// impl_tuple_serialize!(i16, i32); -// impl_tuple_deserialize!(i16, i32); -// impl_tuple_serialize!(i16, isize); -// impl_tuple_deserialize!(i16, isize); -// impl_tuple_serialize!(i16, f32); -// impl_tuple_deserialize!(i16, f32); -// impl_tuple_serialize!(i16, f64); -// impl_tuple_deserialize!(i16, f64); -// impl_tuple_serialize!(i16, bool); -// impl_tuple_deserialize!(i16, bool); -// impl_tuple_serialize!(i16, ZBuf); -// impl_tuple_deserialize!(i16, ZBuf); -// impl_tuple_serialize!(i16, Vec); -// impl_tuple_deserialize!(i16, Vec); -// impl_tuple_serialize!(i16, String); -// impl_tuple_deserialize!(i16, String); -// impl_tuple_serialize!(i16, &[u8]); -// impl_tuple_serialize!(i32, u8); -// impl_tuple_deserialize!(i32, u8); -// impl_tuple_serialize!(i32, u16); -// impl_tuple_deserialize!(i32, u16); -// impl_tuple_serialize!(i32, u32); -// impl_tuple_deserialize!(i32, u32); -// impl_tuple_serialize!(i32, u64); -// impl_tuple_deserialize!(i32, u64); -// impl_tuple_serialize!(i32, usize); -// impl_tuple_deserialize!(i32, usize); -// impl_tuple_serialize!(i32, i8); -// impl_tuple_deserialize!(i32, i8); -// impl_tuple_serialize!(i32, i16); -// impl_tuple_deserialize!(i32, i16); -// impl_tuple_serialize!(i32, i32); -// impl_tuple_deserialize!(i32, i32); -// impl_tuple_serialize!(i32, isize); -// impl_tuple_deserialize!(i32, isize); -// impl_tuple_serialize!(i32, f32); -// impl_tuple_deserialize!(i32, f32); -// impl_tuple_serialize!(i32, f64); -// impl_tuple_deserialize!(i32, f64); -// impl_tuple_serialize!(i32, bool); -// impl_tuple_deserialize!(i32, bool); -// impl_tuple_serialize!(i32, ZBuf); -// impl_tuple_deserialize!(i32, ZBuf); -// impl_tuple_serialize!(i32, Vec); -// impl_tuple_deserialize!(i32, Vec); -// impl_tuple_serialize!(i32, String); -// impl_tuple_deserialize!(i32, String); -// impl_tuple_serialize!(i32, &[u8]); -// impl_tuple_serialize!(isize, u8); -// impl_tuple_deserialize!(isize, u8); -// impl_tuple_serialize!(isize, u16); -// impl_tuple_deserialize!(isize, u16); -// impl_tuple_serialize!(isize, u32); -// impl_tuple_deserialize!(isize, u32); -// impl_tuple_serialize!(isize, u64); -// impl_tuple_deserialize!(isize, u64); -// impl_tuple_serialize!(isize, usize); -// impl_tuple_deserialize!(isize, usize); -// impl_tuple_serialize!(isize, i8); -// impl_tuple_deserialize!(isize, i8); -// impl_tuple_serialize!(isize, i16); -// impl_tuple_deserialize!(isize, i16); -// impl_tuple_serialize!(isize, i32); -// impl_tuple_deserialize!(isize, i32); -// impl_tuple_serialize!(isize, isize); -// impl_tuple_deserialize!(isize, isize); -// impl_tuple_serialize!(isize, f32); -// impl_tuple_deserialize!(isize, f32); -// impl_tuple_serialize!(isize, f64); -// impl_tuple_deserialize!(isize, f64); -// impl_tuple_serialize!(isize, bool); -// impl_tuple_deserialize!(isize, bool); -// impl_tuple_serialize!(isize, ZBuf); -// impl_tuple_deserialize!(isize, ZBuf); -// impl_tuple_serialize!(isize, Vec); -// impl_tuple_deserialize!(isize, Vec); -// impl_tuple_serialize!(isize, String); -// impl_tuple_deserialize!(isize, String); -// impl_tuple_serialize!(isize, &[u8]); -// impl_tuple_serialize!(f32, u8); -// impl_tuple_deserialize!(f32, u8); -// impl_tuple_serialize!(f32, u16); -// impl_tuple_deserialize!(f32, u16); -// impl_tuple_serialize!(f32, u32); -// impl_tuple_deserialize!(f32, u32); -// impl_tuple_serialize!(f32, u64); -// impl_tuple_deserialize!(f32, u64); -// impl_tuple_serialize!(f32, usize); -// impl_tuple_deserialize!(f32, usize); -// impl_tuple_serialize!(f32, i8); -// impl_tuple_deserialize!(f32, i8); -// impl_tuple_serialize!(f32, i16); -// impl_tuple_deserialize!(f32, i16); -// impl_tuple_serialize!(f32, i32); -// impl_tuple_deserialize!(f32, i32); -// impl_tuple_serialize!(f32, isize); -// impl_tuple_deserialize!(f32, isize); -// impl_tuple_serialize!(f32, f32); -// impl_tuple_deserialize!(f32, f32); -// impl_tuple_serialize!(f32, f64); -// impl_tuple_deserialize!(f32, f64); -// impl_tuple_serialize!(f32, bool); -// impl_tuple_deserialize!(f32, bool); -// impl_tuple_serialize!(f32, ZBuf); -// impl_tuple_deserialize!(f32, ZBuf); -// impl_tuple_serialize!(f32, Vec); -// impl_tuple_deserialize!(f32, Vec); -// impl_tuple_serialize!(f32, String); -// impl_tuple_deserialize!(f32, String); -// impl_tuple_serialize!(f32, &[u8]); -// impl_tuple_serialize!(f64, u8); -// impl_tuple_deserialize!(f64, u8); -// impl_tuple_serialize!(f64, u16); -// impl_tuple_deserialize!(f64, u16); -// impl_tuple_serialize!(f64, u32); -// impl_tuple_deserialize!(f64, u32); -// impl_tuple_serialize!(f64, u64); -// impl_tuple_deserialize!(f64, u64); -// impl_tuple_serialize!(f64, usize); -// impl_tuple_deserialize!(f64, usize); -// impl_tuple_serialize!(f64, i8); -// impl_tuple_deserialize!(f64, i8); -// impl_tuple_serialize!(f64, i16); -// impl_tuple_deserialize!(f64, i16); -// impl_tuple_serialize!(f64, i32); -// impl_tuple_deserialize!(f64, i32); -// impl_tuple_serialize!(f64, isize); -// impl_tuple_deserialize!(f64, isize); -// impl_tuple_serialize!(f64, f32); -// impl_tuple_deserialize!(f64, f32); -// impl_tuple_serialize!(f64, f64); -// impl_tuple_deserialize!(f64, f64); -// impl_tuple_serialize!(f64, bool); -// impl_tuple_deserialize!(f64, bool); -// impl_tuple_serialize!(f64, ZBuf); -// impl_tuple_deserialize!(f64, ZBuf); -// impl_tuple_serialize!(f64, Vec); -// impl_tuple_deserialize!(f64, Vec); -// impl_tuple_serialize!(f64, String); -// impl_tuple_deserialize!(f64, String); -// impl_tuple_serialize!(f64, &[u8]); -// impl_tuple_serialize!(bool, u8); -// impl_tuple_deserialize!(bool, u8); -// impl_tuple_serialize!(bool, u16); -// impl_tuple_deserialize!(bool, u16); -// impl_tuple_serialize!(bool, u32); -// impl_tuple_deserialize!(bool, u32); -// impl_tuple_serialize!(bool, u64); -// impl_tuple_deserialize!(bool, u64); -// impl_tuple_serialize!(bool, usize); -// impl_tuple_deserialize!(bool, usize); -// impl_tuple_serialize!(bool, i8); -// impl_tuple_deserialize!(bool, i8); -// impl_tuple_serialize!(bool, i16); -// impl_tuple_deserialize!(bool, i16); -// impl_tuple_serialize!(bool, i32); -// impl_tuple_deserialize!(bool, i32); -// impl_tuple_serialize!(bool, isize); -// impl_tuple_deserialize!(bool, isize); -// impl_tuple_serialize!(bool, f32); -// impl_tuple_deserialize!(bool, f32); -// impl_tuple_serialize!(bool, f64); -// impl_tuple_deserialize!(bool, f64); -// impl_tuple_serialize!(bool, bool); -// impl_tuple_deserialize!(bool, bool); -// impl_tuple_serialize!(bool, ZBuf); -// impl_tuple_deserialize!(bool, ZBuf); -// impl_tuple_serialize!(bool, Vec); -// impl_tuple_deserialize!(bool, Vec); -// impl_tuple_serialize!(bool, String); -// impl_tuple_deserialize!(bool, String); -// impl_tuple_serialize!(bool, &[u8]); -// impl_tuple_serialize!(ZBuf, u8); -// impl_tuple_deserialize!(ZBuf, u8); -// impl_tuple_serialize!(ZBuf, u16); -// impl_tuple_deserialize!(ZBuf, u16); -// impl_tuple_serialize!(ZBuf, u32); -// impl_tuple_deserialize!(ZBuf, u32); -// impl_tuple_serialize!(ZBuf, u64); -// impl_tuple_deserialize!(ZBuf, u64); -// impl_tuple_serialize!(ZBuf, usize); -// impl_tuple_deserialize!(ZBuf, usize); -// impl_tuple_serialize!(ZBuf, i8); -// impl_tuple_deserialize!(ZBuf, i8); -// impl_tuple_serialize!(ZBuf, i16); -// impl_tuple_deserialize!(ZBuf, i16); -// impl_tuple_serialize!(ZBuf, i32); -// impl_tuple_deserialize!(ZBuf, i32); -// impl_tuple_serialize!(ZBuf, isize); -// impl_tuple_deserialize!(ZBuf, isize); -// impl_tuple_serialize!(ZBuf, f32); -// impl_tuple_deserialize!(ZBuf, f32); -// impl_tuple_serialize!(ZBuf, f64); -// impl_tuple_deserialize!(ZBuf, f64); -// impl_tuple_serialize!(ZBuf, bool); -// impl_tuple_deserialize!(ZBuf, bool); -// impl_tuple_serialize!(ZBuf, ZBuf); -// impl_tuple_deserialize!(ZBuf, ZBuf); -// impl_tuple_serialize!(ZBuf, Vec); -// impl_tuple_deserialize!(ZBuf, Vec); -// impl_tuple_serialize!(ZBuf, String); -// impl_tuple_deserialize!(ZBuf, String); -// impl_tuple_serialize!(ZBuf, &[u8]); -// impl_tuple_serialize!(Vec, u8); -// impl_tuple_deserialize!(Vec, u8); -// impl_tuple_serialize!(Vec, u16); -// impl_tuple_deserialize!(Vec, u16); -// impl_tuple_serialize!(Vec, u32); -// impl_tuple_deserialize!(Vec, u32); -// impl_tuple_serialize!(Vec, u64); -// impl_tuple_deserialize!(Vec, u64); -// impl_tuple_serialize!(Vec, usize); -// impl_tuple_deserialize!(Vec, usize); -// impl_tuple_serialize!(Vec, i8); -// impl_tuple_deserialize!(Vec, i8); -// impl_tuple_serialize!(Vec, i16); -// impl_tuple_deserialize!(Vec, i16); -// impl_tuple_serialize!(Vec, i32); -// impl_tuple_deserialize!(Vec, i32); -// impl_tuple_serialize!(Vec, isize); -// impl_tuple_deserialize!(Vec, isize); -// impl_tuple_serialize!(Vec, f32); -// impl_tuple_deserialize!(Vec, f32); -// impl_tuple_serialize!(Vec, f64); -// impl_tuple_deserialize!(Vec, f64); -// impl_tuple_serialize!(Vec, bool); -// impl_tuple_deserialize!(Vec, bool); -// impl_tuple_serialize!(Vec, ZBuf); -// impl_tuple_deserialize!(Vec, ZBuf); -// impl_tuple_serialize!(Vec, Vec); -// impl_tuple_deserialize!(Vec, Vec); -// impl_tuple_serialize!(Vec, String); -// impl_tuple_deserialize!(Vec, String); -// impl_tuple_serialize!(Vec, &[u8]); -// impl_tuple_serialize!(String, u8); -// impl_tuple_deserialize!(String, u8); -// impl_tuple_serialize!(String, u16); -// impl_tuple_deserialize!(String, u16); -// impl_tuple_serialize!(String, u32); -// impl_tuple_deserialize!(String, u32); -// impl_tuple_serialize!(String, u64); -// impl_tuple_deserialize!(String, u64); -// impl_tuple_serialize!(String, usize); -// impl_tuple_deserialize!(String, usize); -// impl_tuple_serialize!(String, i8); -// impl_tuple_deserialize!(String, i8); -// impl_tuple_serialize!(String, i16); -// impl_tuple_deserialize!(String, i16); -// impl_tuple_serialize!(String, i32); -// impl_tuple_deserialize!(String, i32); -// impl_tuple_serialize!(String, isize); -// impl_tuple_deserialize!(String, isize); -// impl_tuple_serialize!(String, f32); -// impl_tuple_deserialize!(String, f32); -// impl_tuple_serialize!(String, f64); -// impl_tuple_deserialize!(String, f64); -// impl_tuple_serialize!(String, bool); -// impl_tuple_deserialize!(String, bool); -// impl_tuple_serialize!(String, ZBuf); -// impl_tuple_deserialize!(String, ZBuf); -// impl_tuple_serialize!(String, Vec); -// impl_tuple_deserialize!(String, Vec); -// impl_tuple_serialize!(String, String); -// impl_tuple_deserialize!(String, String); -// impl_tuple_serialize!(String, &[u8]); -// impl_tuple_serialize!(&[u8], u8); -// impl_tuple_serialize!(&[u8], u16); -// impl_tuple_serialize!(&[u8], u32); -// impl_tuple_serialize!(&[u8], u64); -// impl_tuple_serialize!(&[u8], usize); -// impl_tuple_serialize!(&[u8], i8); -// impl_tuple_serialize!(&[u8], i16); -// impl_tuple_serialize!(&[u8], i32); -// impl_tuple_serialize!(&[u8], isize); -// impl_tuple_serialize!(&[u8], f32); -// impl_tuple_serialize!(&[u8], f64); -// impl_tuple_serialize!(&[u8], bool); -// impl_tuple_serialize!(&[u8], ZBuf); -// impl_tuple_serialize!(&[u8], Vec); -// impl_tuple_serialize!(&[u8], String); -// impl_tuple_serialize!(&[u8], &[u8]); -// impl_iterator_serialize!(u8); -// impl_iterator_serialize!(u16); -// impl_iterator_serialize!(u32); -// impl_iterator_serialize!(u64); -// impl_iterator_serialize!(usize); -// impl_iterator_serialize!(i8); -// impl_iterator_serialize!(i16); -// impl_iterator_serialize!(i32); -// impl_iterator_serialize!(isize); -// impl_iterator_serialize!(f32); -// impl_iterator_serialize!(f64); -// impl_iterator_serialize!(bool); -// impl_iterator_serialize!(ZBuf); -// impl_iterator_serialize!(Vec); -// impl_iterator_serialize!(String); -// impl_iterator_serialize!(&[u8]); + let v: [usize; 5] = [0, 1, 2, 3, 4]; + let p = Payload::from_iter(v.iter()); + for (i, t) in p.iter::().enumerate() { + assert_eq!(i, t); + } + + use std::collections::HashMap; + let mut hm: HashMap = HashMap::new(); + hm.insert(0, 0); + hm.insert(1, 1); + let p = Payload::from_iter(hm.iter()); + // for (i, (k, v)) in p.iter::<(usize, usize)>().enumerate() { + // assert_eq!(i, k); + // assert_eq!(i, v); + // } + } +} From a25676b4c468c408c31f74d2a896be315a1d7f1a Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Mon, 8 Apr 2024 20:08:36 +0200 Subject: [PATCH 03/19] Improve payload serde --- zenoh/src/payload.rs | 272 ++++++++++++++++++++++++++++++++----------- 1 file changed, 202 insertions(+), 70 deletions(-) diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index ed8c1b98c3..3c4709a6ae 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -211,6 +211,20 @@ impl From for Payload { } } +impl Serialize<&ZBuf> for ZSerde { + type Output = Payload; + + fn serialize(self, t: &ZBuf) -> Self::Output { + Payload::new(t.clone()) + } +} + +impl From<&ZBuf> for Payload { + fn from(t: &ZBuf) -> Self { + ZSerde.serialize(t) + } +} + impl Deserialize<'_, ZBuf> for ZSerde { type Error = Infallible; @@ -246,6 +260,20 @@ impl From> for Payload { } } +impl Serialize<&Vec> for ZSerde { + type Output = Payload; + + fn serialize(self, t: &Vec) -> Self::Output { + Payload::new(t.clone()) + } +} + +impl From<&Vec> for Payload { + fn from(t: &Vec) -> Self { + ZSerde.serialize(t) + } +} + impl Deserialize<'_, Vec> for ZSerde { type Error = Infallible; @@ -296,6 +324,20 @@ impl From> for Payload { } } +impl<'a> Serialize<&Cow<'a, [u8]>> for ZSerde { + type Output = Payload; + + fn serialize(self, t: &Cow<'a, [u8]>) -> Self::Output { + Payload::new(t.to_vec()) + } +} + +impl From<&Cow<'_, [u8]>> for Payload { + fn from(t: &Cow<'_, [u8]>) -> Self { + ZSerde.serialize(t) + } +} + impl<'a> Deserialize<'a, Cow<'a, [u8]>> for ZSerde { type Error = Infallible; @@ -325,6 +367,20 @@ impl From for Payload { } } +impl Serialize<&String> for ZSerde { + type Output = Payload; + + fn serialize(self, s: &String) -> Self::Output { + Payload::new(s.clone().into_bytes()) + } +} + +impl From<&String> for Payload { + fn from(t: &String) -> Self { + ZSerde.serialize(t) + } +} + impl Deserialize<'_, String> for ZSerde { type Error = FromUtf8Error; @@ -380,6 +436,20 @@ impl From> for Payload { } } +impl<'a> Serialize<&Cow<'a, str>> for ZSerde { + type Output = Payload; + + fn serialize(self, s: &Cow<'a, str>) -> Self::Output { + Self.serialize(s.to_string()) + } +} + +impl From<&Cow<'_, str>> for Payload { + fn from(t: &Cow<'_, str>) -> Self { + ZSerde.serialize(t) + } +} + impl<'a> Deserialize<'a, Cow<'a, str>> for ZSerde { type Error = FromUtf8Error; @@ -437,20 +507,6 @@ macro_rules! impl_int { } } - impl Serialize<&mut $t> for ZSerde { - type Output = Payload; - - fn serialize(self, t: &mut $t) -> Self::Output { - ZSerde.serialize(*t) - } - } - - impl From<&mut $t> for Payload { - fn from(t: &mut $t) -> Self { - ZSerde.serialize(t) - } - } - impl<'a> Deserialize<'a, $t> for ZSerde { type Error = ZDeserializeError; @@ -522,6 +578,20 @@ impl From for Payload { } } +impl Serialize<&bool> for ZSerde { + type Output = Payload; + + fn serialize(self, t: &bool) -> Self::Output { + ZSerde.serialize(*t) + } +} + +impl From<&bool> for Payload { + fn from(t: &bool) -> Self { + ZSerde.serialize(t) + } +} + impl Deserialize<'_, bool> for ZSerde { type Error = ZDeserializeError; @@ -535,6 +605,14 @@ impl Deserialize<'_, bool> for ZSerde { } } +impl TryFrom for bool { + type Error = ZDeserializeError; + + fn try_from(value: Payload) -> Result { + ZSerde.deserialize(&value) + } +} + impl TryFrom<&Payload> for bool { type Error = ZDeserializeError; @@ -545,36 +623,36 @@ impl TryFrom<&Payload> for bool { // - Zenoh advanced types encoders/decoders // JSON -impl Serialize<&serde_json::Value> for ZSerde { +impl Serialize for ZSerde { type Output = Result; - fn serialize(self, t: &serde_json::Value) -> Self::Output { - let mut payload = Payload::empty(); - serde_json::to_writer(payload.0.writer(), t)?; - Ok(payload) + fn serialize(self, t: serde_json::Value) -> Self::Output { + ZSerde.serialize(&t) } } -impl TryFrom<&serde_json::Value> for Payload { +impl TryFrom for Payload { type Error = serde_json::Error; - fn try_from(value: &serde_json::Value) -> Result { - ZSerde.serialize(value) + fn try_from(value: serde_json::Value) -> Result { + ZSerde.serialize(&value) } } -impl Serialize for ZSerde { +impl Serialize<&serde_json::Value> for ZSerde { type Output = Result; - fn serialize(self, t: serde_json::Value) -> Self::Output { - Self.serialize(&t) + fn serialize(self, t: &serde_json::Value) -> Self::Output { + let mut payload = Payload::empty(); + serde_json::to_writer(payload.0.writer(), t)?; + Ok(payload) } } -impl TryFrom for Payload { +impl TryFrom<&serde_json::Value> for Payload { type Error = serde_json::Error; - fn try_from(value: serde_json::Value) -> Result { + fn try_from(value: &serde_json::Value) -> Result { ZSerde.serialize(value) } } @@ -587,6 +665,14 @@ impl Deserialize<'_, serde_json::Value> for ZSerde { } } +impl TryFrom for serde_json::Value { + type Error = serde_json::Error; + + fn try_from(value: Payload) -> Result { + ZSerde.deserialize(&value) + } +} + impl TryFrom<&Payload> for serde_json::Value { type Error = serde_json::Error; @@ -596,36 +682,36 @@ impl TryFrom<&Payload> for serde_json::Value { } // Yaml -impl Serialize<&serde_yaml::Value> for ZSerde { +impl Serialize for ZSerde { type Output = Result; - fn serialize(self, t: &serde_yaml::Value) -> Self::Output { - let mut payload = Payload::empty(); - serde_yaml::to_writer(payload.0.writer(), t)?; - Ok(payload) + fn serialize(self, t: serde_yaml::Value) -> Self::Output { + Self.serialize(&t) } } -impl TryFrom<&serde_yaml::Value> for Payload { +impl TryFrom for Payload { type Error = serde_yaml::Error; - fn try_from(value: &serde_yaml::Value) -> Result { + fn try_from(value: serde_yaml::Value) -> Result { ZSerde.serialize(value) } } -impl Serialize for ZSerde { +impl Serialize<&serde_yaml::Value> for ZSerde { type Output = Result; - fn serialize(self, t: serde_yaml::Value) -> Self::Output { - Self.serialize(&t) + fn serialize(self, t: &serde_yaml::Value) -> Self::Output { + let mut payload = Payload::empty(); + serde_yaml::to_writer(payload.0.writer(), t)?; + Ok(payload) } } -impl TryFrom for Payload { +impl TryFrom<&serde_yaml::Value> for Payload { type Error = serde_yaml::Error; - fn try_from(value: serde_yaml::Value) -> Result { + fn try_from(value: &serde_yaml::Value) -> Result { ZSerde.serialize(value) } } @@ -638,6 +724,14 @@ impl Deserialize<'_, serde_yaml::Value> for ZSerde { } } +impl TryFrom for serde_yaml::Value { + type Error = serde_yaml::Error; + + fn try_from(value: Payload) -> Result { + ZSerde.deserialize(&value) + } +} + impl TryFrom<&Payload> for serde_yaml::Value { type Error = serde_yaml::Error; @@ -647,36 +741,36 @@ impl TryFrom<&Payload> for serde_yaml::Value { } // CBOR -impl Serialize<&serde_cbor::Value> for ZSerde { +impl Serialize for ZSerde { type Output = Result; - fn serialize(self, t: &serde_cbor::Value) -> Self::Output { - let mut payload = Payload::empty(); - serde_cbor::to_writer(payload.0.writer(), t)?; - Ok(payload) + fn serialize(self, t: serde_cbor::Value) -> Self::Output { + Self.serialize(&t) } } -impl TryFrom<&serde_cbor::Value> for Payload { +impl TryFrom for Payload { type Error = serde_cbor::Error; - fn try_from(value: &serde_cbor::Value) -> Result { + fn try_from(value: serde_cbor::Value) -> Result { ZSerde.serialize(value) } } -impl Serialize for ZSerde { +impl Serialize<&serde_cbor::Value> for ZSerde { type Output = Result; - fn serialize(self, t: serde_cbor::Value) -> Self::Output { - Self.serialize(&t) + fn serialize(self, t: &serde_cbor::Value) -> Self::Output { + let mut payload = Payload::empty(); + serde_cbor::to_writer(payload.0.writer(), t)?; + Ok(payload) } } -impl TryFrom for Payload { +impl TryFrom<&serde_cbor::Value> for Payload { type Error = serde_cbor::Error; - fn try_from(value: serde_cbor::Value) -> Result { + fn try_from(value: &serde_cbor::Value) -> Result { ZSerde.serialize(value) } } @@ -689,6 +783,14 @@ impl Deserialize<'_, serde_cbor::Value> for ZSerde { } } +impl TryFrom for serde_cbor::Value { + type Error = serde_cbor::Error; + + fn try_from(value: Payload) -> Result { + ZSerde.deserialize(&value) + } +} + impl TryFrom<&Payload> for serde_cbor::Value { type Error = serde_cbor::Error; @@ -698,6 +800,22 @@ impl TryFrom<&Payload> for serde_cbor::Value { } // Pickle +impl Serialize for ZSerde { + type Output = Result; + + fn serialize(self, t: serde_pickle::Value) -> Self::Output { + Self.serialize(&t) + } +} + +impl TryFrom for Payload { + type Error = serde_pickle::Error; + + fn try_from(value: serde_pickle::Value) -> Result { + ZSerde.serialize(value) + } +} + impl Serialize<&serde_pickle::Value> for ZSerde { type Output = Result; @@ -720,27 +838,19 @@ impl TryFrom<&serde_pickle::Value> for Payload { } } -impl Serialize for ZSerde { - type Output = Result; - - fn serialize(self, t: serde_pickle::Value) -> Self::Output { - Self.serialize(&t) - } -} - -impl TryFrom for Payload { +impl Deserialize<'_, serde_pickle::Value> for ZSerde { type Error = serde_pickle::Error; - fn try_from(value: serde_pickle::Value) -> Result { - ZSerde.serialize(value) + fn deserialize(self, v: &Payload) -> Result { + serde_pickle::value_from_reader(v.reader(), serde_pickle::DeOptions::default()) } } -impl Deserialize<'_, serde_pickle::Value> for ZSerde { +impl TryFrom for serde_pickle::Value { type Error = serde_pickle::Error; - fn deserialize(self, v: &Payload) -> Result { - serde_pickle::value_from_reader(v.reader(), serde_pickle::DeOptions::default()) + fn try_from(value: Payload) -> Result { + ZSerde.deserialize(&value) } } @@ -761,6 +871,12 @@ impl Serialize> for ZSerde { Payload::new(t) } } +#[cfg(feature = "shared-memory")] +impl From> for Payload { + fn from(t: Arc) -> Self { + ZSerde.serialize(t) + } +} #[cfg(feature = "shared-memory")] impl Serialize> for ZSerde { @@ -772,6 +888,13 @@ impl Serialize> for ZSerde { } } +#[cfg(feature = "shared-memory")] +impl From> for Payload { + fn from(t: Box) -> Self { + ZSerde.serialize(t) + } +} + #[cfg(feature = "shared-memory")] impl Serialize for ZSerde { type Output = Payload; @@ -781,6 +904,13 @@ impl Serialize for ZSerde { } } +#[cfg(feature = "shared-memory")] +impl From for Payload { + fn from(t: SharedMemoryBuf) -> Self { + ZSerde.serialize(t) + } +} + // Tuple impl Serialize<(A, B)> for ZSerde where @@ -859,7 +989,7 @@ where } } -// For convenience to always convert a Value the examples +// For convenience to always convert a Value in the examples #[derive(Debug, Clone, PartialEq, Eq)] pub enum StringOrBase64 { String(String), @@ -1000,7 +1130,9 @@ mod tests { // Iterator let v: [usize; 5] = [0, 1, 2, 3, 4]; + println!("Serialize:\t{:?}", v); let p = Payload::from_iter(v.iter()); + println!("Deerialize:\t{:?}", p); for (i, t) in p.iter::().enumerate() { assert_eq!(i, t); } @@ -1009,10 +1141,10 @@ mod tests { let mut hm: HashMap = HashMap::new(); hm.insert(0, 0); hm.insert(1, 1); + println!("Serialize:\t{:?}", hm); let p = Payload::from_iter(hm.iter()); - // for (i, (k, v)) in p.iter::<(usize, usize)>().enumerate() { - // assert_eq!(i, k); - // assert_eq!(i, v); - // } + println!("Deerialize:\t{:?}", p); + let o: HashMap = HashMap::from_iter(p.iter()); + assert_eq!(hm, o); } } From d0246076a3260e40a0df4fc0d0c2357126a37793 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 9 Apr 2024 09:38:42 +0200 Subject: [PATCH 04/19] [u8;N] payload support. from_reader functionality. --- zenoh/src/payload.rs | 88 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index 3c4709a6ae..a65843dcaf 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -14,6 +14,7 @@ //! Payload primitives. use crate::buffers::ZBuf; +use std::io::Read; use std::marker::PhantomData; use std::{ borrow::Cow, convert::Infallible, fmt::Debug, ops::Deref, string::FromUtf8Error, sync::Arc, @@ -79,6 +80,16 @@ impl Payload { PayloadReader(self.0.reader()) } + /// Build a [`Payload`] from a [`Reader`]. This operation copies data from the reader. + pub fn from_reader(mut reader: R) -> Result + where + R: std::io::Read, + { + let mut buf: Vec = vec![]; + reader.read_to_end(&mut buf)?; + Ok(Payload::new(buf)) + } + /// Get a [`PayloadReader`] implementing [`std::io::Read`] trait. pub fn iter<'a, T>(&'a self) -> PayloadIterator<'a, T> where @@ -91,10 +102,7 @@ impl Payload { _t: PhantomData::, } } -} -/// Provide some facilities specific to the Rust API to encode/decode a [`Value`] with an `Serialize`. -impl Payload { /// Encode an object of type `T` as a [`Value`] using the [`ZSerde`]. /// /// ```rust @@ -125,6 +133,8 @@ impl Payload { } /// A reader that implements [`std::io::Read`] trait to read from a [`Payload`]. +#[repr(transparent)] +#[derive(Debug)] pub struct PayloadReader<'a>(ZBufReader<'a>); impl std::io::Read for PayloadReader<'_> { @@ -135,6 +145,8 @@ impl std::io::Read for PayloadReader<'_> { /// An iterator that implements [`std::iter::Iterator`] trait to iterate on values `T` in a [`Payload`]. /// Note that [`Payload`] contains a serialized version of `T` and iterating over a [`Payload`] performs lazy deserialization. +#[repr(transparent)] +#[derive(Debug)] pub struct PayloadIterator<'a, T> where ZSerde: Deserialize<'a, T>, @@ -245,6 +257,65 @@ impl From<&Payload> for ZBuf { } } +// [u8; N] +impl Serialize<[u8; N]> for ZSerde { + type Output = Payload; + + fn serialize(self, t: [u8; N]) -> Self::Output { + Payload::new(t) + } +} + +impl From<[u8; N]> for Payload { + fn from(t: [u8; N]) -> Self { + ZSerde.serialize(t) + } +} + +impl Serialize<&[u8; N]> for ZSerde { + type Output = Payload; + + fn serialize(self, t: &[u8; N]) -> Self::Output { + Payload::new(*t) + } +} + +impl From<&[u8; N]> for Payload { + fn from(t: &[u8; N]) -> Self { + ZSerde.serialize(t) + } +} + +impl Deserialize<'_, [u8; N]> for ZSerde { + type Error = ZDeserializeError; + + fn deserialize(self, v: &Payload) -> Result<[u8; N], Self::Error> { + if v.0.len() != N { + return Err(ZDeserializeError); + } + let mut dst = [0u8; N]; + let mut reader = v.reader(); + reader.read_exact(&mut dst).map_err(|_| ZDeserializeError)?; + Ok(dst) + } +} + +impl TryFrom for [u8; N] { + type Error = ZDeserializeError; + + fn try_from(value: Payload) -> Result { + ZSerde.deserialize(&value) + } +} + +impl TryFrom<&Payload> for [u8; N] { + type Error = ZDeserializeError; + + fn try_from(value: &Payload) -> Result { + ZSerde.deserialize(value) + } +} + // Vec impl Serialize> for ZSerde { type Output = Payload; @@ -1137,6 +1208,17 @@ mod tests { assert_eq!(i, t); } + let mut v = vec![[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]; + println!("Serialize:\t{:?}", v); + let p = Payload::from_iter(v.drain(..)); + println!("Deerialize:\t{:?}", p); + let mut iter = p.iter::<[u8; 4]>(); + assert_eq!(iter.next().unwrap(), [0, 1, 2, 3]); + assert_eq!(iter.next().unwrap(), [4, 5, 6, 7]); + assert_eq!(iter.next().unwrap(), [8, 9, 10, 11]); + assert_eq!(iter.next().unwrap(), [12, 13, 14, 15]); + assert!(iter.next().is_none()); + use std::collections::HashMap; let mut hm: HashMap = HashMap::new(); hm.insert(0, 0); From 2a6bade7cc2d932cee30c18f97848c74511097cd Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 9 Apr 2024 09:45:05 +0200 Subject: [PATCH 05/19] Improve payload test --- zenoh/src/payload.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index a65843dcaf..4899dd97e6 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -1224,9 +1224,9 @@ mod tests { hm.insert(0, 0); hm.insert(1, 1); println!("Serialize:\t{:?}", hm); - let p = Payload::from_iter(hm.iter()); + let p = Payload::from_iter(hm.drain()); println!("Deerialize:\t{:?}", p); - let o: HashMap = HashMap::from_iter(p.iter()); + let o = HashMap::from_iter(p.iter::<(usize, usize)>()); assert_eq!(hm, o); } } From 6793a6b8741fc055633c28e568c2fc8237abbeea Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 9 Apr 2024 12:20:09 +0200 Subject: [PATCH 06/19] Payload zserde improvement --- zenoh/src/payload.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index 4899dd97e6..59ad8b79b5 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -540,7 +540,7 @@ impl<'a> TryFrom<&'a Payload> for Cow<'a, str> { // - Integers impl macro_rules! impl_int { - ($t:ty, $encoding:expr) => { + ($t:ty) => { impl Serialize<$t> for ZSerde { type Output = Payload; @@ -615,22 +615,22 @@ macro_rules! impl_int { } // Zenoh unsigned integers -impl_int!(u8, ZSerde::ZENOH_UINT); -impl_int!(u16, ZSerde::ZENOH_UINT); -impl_int!(u32, ZSerde::ZENOH_UINT); -impl_int!(u64, ZSerde::ZENOH_UINT); -impl_int!(usize, ZSerde::ZENOH_UINT); +impl_int!(u8); +impl_int!(u16); +impl_int!(u32); +impl_int!(u64); +impl_int!(usize); // Zenoh signed integers -impl_int!(i8, ZSerde::ZENOH_INT); -impl_int!(i16, ZSerde::ZENOH_INT); -impl_int!(i32, ZSerde::ZENOH_INT); -impl_int!(i64, ZSerde::ZENOH_INT); -impl_int!(isize, ZSerde::ZENOH_INT); +impl_int!(i8); +impl_int!(i16); +impl_int!(i32); +impl_int!(i64); +impl_int!(isize); // Zenoh floats -impl_int!(f32, ZSerde::ZENOH_FLOAT); -impl_int!(f64, ZSerde::ZENOH_FLOAT); +impl_int!(f32); +impl_int!(f64); // Zenoh bool impl Serialize for ZSerde { @@ -1203,7 +1203,7 @@ mod tests { let v: [usize; 5] = [0, 1, 2, 3, 4]; println!("Serialize:\t{:?}", v); let p = Payload::from_iter(v.iter()); - println!("Deerialize:\t{:?}", p); + println!("Deserialize:\t{:?}", p); for (i, t) in p.iter::().enumerate() { assert_eq!(i, t); } @@ -1211,7 +1211,7 @@ mod tests { let mut v = vec![[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]; println!("Serialize:\t{:?}", v); let p = Payload::from_iter(v.drain(..)); - println!("Deerialize:\t{:?}", p); + println!("Deserialize:\t{:?}", p); let mut iter = p.iter::<[u8; 4]>(); assert_eq!(iter.next().unwrap(), [0, 1, 2, 3]); assert_eq!(iter.next().unwrap(), [4, 5, 6, 7]); @@ -1225,7 +1225,7 @@ mod tests { hm.insert(1, 1); println!("Serialize:\t{:?}", hm); let p = Payload::from_iter(hm.drain()); - println!("Deerialize:\t{:?}", p); + println!("Deserialize:\t{:?}", p); let o = HashMap::from_iter(p.iter::<(usize, usize)>()); assert_eq!(hm, o); } From 7240f0169556a66fb4abca47dcfbcce736a01e53 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 9 Apr 2024 12:22:08 +0200 Subject: [PATCH 07/19] Fix encoding doc: suffix to schema --- commons/zenoh-codec/src/core/encoding.rs | 4 ++-- commons/zenoh-protocol/src/core/encoding.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/commons/zenoh-codec/src/core/encoding.rs b/commons/zenoh-codec/src/core/encoding.rs index cfbe0084ba..c8033cdd5f 100644 --- a/commons/zenoh-codec/src/core/encoding.rs +++ b/commons/zenoh-codec/src/core/encoding.rs @@ -62,13 +62,13 @@ where fn read(self, reader: &mut R) -> Result { let zodec = Zenoh080Bounded::::new(); let id: u32 = zodec.read(&mut *reader)?; - let (id, has_suffix) = ( + let (id, has_schema) = ( (id >> 1) as EncodingId, imsg::has_flag(id as u8, flag::S as u8), ); let mut schema = None; - if has_suffix { + if has_schema { let zodec = Zenoh080Bounded::::new(); schema = Some(zodec.read(&mut *reader)?); } diff --git a/commons/zenoh-protocol/src/core/encoding.rs b/commons/zenoh-protocol/src/core/encoding.rs index 9b9aa5bf2f..70afdbf143 100644 --- a/commons/zenoh-protocol/src/core/encoding.rs +++ b/commons/zenoh-protocol/src/core/encoding.rs @@ -18,8 +18,8 @@ pub type EncodingId = u16; /// [`Encoding`] is a metadata that indicates how the data payload should be interpreted. /// For wire-efficiency and extensibility purposes, Zenoh defines an [`Encoding`] as -/// composed of an unsigned integer prefix and a string suffix. The actual meaning of the -/// prefix and suffix are out-of-scope of the protocol definition. Therefore, Zenoh does not +/// composed of an unsigned integer prefix and a bytes schema. The actual meaning of the +/// prefix and schema are out-of-scope of the protocol definition. Therefore, Zenoh does not /// impose any encoding mapping and users are free to use any mapping they like. /// Nevertheless, it is worth highlighting that Zenoh still provides a default mapping as part /// of the API as per user convenience. That mapping has no impact on the Zenoh protocol definition. @@ -40,7 +40,7 @@ pub struct Encoding { /// +---------------+ /// ``` pub mod flag { - pub const S: u32 = 1; // 0x01 Suffix if S==1 then suffix is present + pub const S: u32 = 1; // 0x01 Suffix if S==1 then schema is present } impl Encoding { From 989509c447df98771abcfaea786e203e885db5b5 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 9 Apr 2024 17:11:28 +0200 Subject: [PATCH 08/19] impl Seek for ZBufReader --- commons/zenoh-buffers/src/zbuf.rs | 144 +++++++++++++++++++++++++++--- zenoh/src/payload.rs | 7 +- 2 files changed, 134 insertions(+), 17 deletions(-) diff --git a/commons/zenoh-buffers/src/zbuf.rs b/commons/zenoh-buffers/src/zbuf.rs index fd86f454af..6fded06ae7 100644 --- a/commons/zenoh-buffers/src/zbuf.rs +++ b/commons/zenoh-buffers/src/zbuf.rs @@ -21,6 +21,8 @@ use crate::{ }; use alloc::{sync::Arc, vec::Vec}; use core::{cmp, iter, mem, num::NonZeroUsize, ops::RangeBounds, ptr}; +#[cfg(feature = "std")] +use std::io; use zenoh_collections::SingleOrVec; fn get_mut_unchecked(arc: &mut Arc) -> &mut T { @@ -270,7 +272,7 @@ impl<'a> Reader for ZBufReader<'a> { } fn read_exact(&mut self, into: &mut [u8]) -> Result<(), DidntRead> { - let len = self.read(into)?; + let len = Reader::read(self, into)?; if len.get() == into.len() { Ok(()) } else { @@ -317,7 +319,7 @@ impl<'a> Reader for ZBufReader<'a> { match (slice.len() - self.cursor.byte).cmp(&len) { cmp::Ordering::Less => { let mut buffer = crate::vec::uninit(len); - self.read_exact(&mut buffer)?; + Reader::read_exact(self, &mut buffer)?; Ok(buffer.into()) } cmp::Ordering::Equal => { @@ -388,18 +390,58 @@ impl<'a> SiphonableReader for ZBufReader<'a> { } #[cfg(feature = "std")] -impl<'a> std::io::Read for ZBufReader<'a> { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { +impl<'a> io::Read for ZBufReader<'a> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { match ::read(self, buf) { Ok(n) => Ok(n.get()), - Err(_) => Err(std::io::Error::new( - std::io::ErrorKind::UnexpectedEof, + Err(_) => Err(io::Error::new( + io::ErrorKind::UnexpectedEof, "UnexpectedEof", )), } } } +#[cfg(feature = "std")] +impl<'a> io::Seek for ZBufReader<'a> { + fn seek(&mut self, pos: io::SeekFrom) -> io::Result { + // Compute the index + let len = self.inner.len(); + let index = match pos { + io::SeekFrom::Start(pos) => pos.try_into().unwrap_or(i64::MAX), + io::SeekFrom::End(pos) => { + pos + i64::try_from(len) + .map_err(|e| io::Error::new(io::ErrorKind::UnexpectedEof, e))? + } + io::SeekFrom::Current(pos) => { + pos + i64::try_from(len - self.remaining()) + .map_err(|e| io::Error::new(io::ErrorKind::UnexpectedEof, e))? + } + }; + + let index = usize::try_from(index) + .map_err(|e| io::Error::new(io::ErrorKind::UnexpectedEof, e))? + .min(len); + + // Seek the position + let mut left = index; + let mut pos = ZBufPos { slice: 0, byte: 0 }; + while let Some(slice) = self.inner.slices.get(pos.slice) { + let len = slice.len(); + if len >= left { + pos.byte = left; + self.cursor = pos; + return Ok(index as u64); + } else { + left -= len; + } + pos.slice += 1; + } + + Err(io::ErrorKind::UnexpectedEof.into()) + } +} + // ZSlice iterator pub struct ZBufSliceIterator<'a, 'b> { reader: &'a mut ZBufReader<'b>, @@ -614,18 +656,18 @@ impl BacktrackableWriter for ZBufWriter<'_> { } #[cfg(feature = "std")] -impl<'a> std::io::Write for ZBufWriter<'a> { - fn write(&mut self, buf: &[u8]) -> std::io::Result { +impl<'a> io::Write for ZBufWriter<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result { match ::write(self, buf) { Ok(n) => Ok(n.get()), - Err(_) => Err(std::io::Error::new( - std::io::ErrorKind::UnexpectedEof, + Err(_) => Err(io::Error::new( + io::ErrorKind::UnexpectedEof, "UnexpectedEof", )), } } - fn flush(&mut self) -> std::io::Result<()> { + fn flush(&mut self) -> io::Result<()> { Ok(()) } } @@ -668,4 +710,84 @@ mod tests { assert_eq!(zbuf1, zbuf2); } + + #[cfg(feature = "std")] + #[test] + fn zbuf_seek() { + use crate::reader::HasReader; + use std::io::{Seek, SeekFrom}; + + use super::{ZBuf, ZSlice}; + + let slice: ZSlice = [0u8, 1, 2, 3, 4, 5, 6, 7].to_vec().into(); + + let mut zbuf = ZBuf::empty(); + zbuf.push_zslice(slice.subslice(0, 1).unwrap()); + zbuf.push_zslice(slice.subslice(1, 4).unwrap()); + zbuf.push_zslice(slice.subslice(4, 8).unwrap()); + + let mut reader = zbuf.reader(); + + let index = reader.seek(SeekFrom::Start(0)).unwrap(); + assert_eq!(index, 0); + assert_eq!(index, reader.stream_position().unwrap()); + + let index = reader.seek(SeekFrom::Start(4)).unwrap(); + assert_eq!(index, 4); + assert_eq!(index, reader.stream_position().unwrap()); + + let index = reader.seek(SeekFrom::Start(8)).unwrap(); + assert_eq!(index, 8); + assert_eq!(index, reader.stream_position().unwrap()); + + let index = reader.seek(SeekFrom::Start(u64::MAX)).unwrap(); + assert_eq!(index, 8); + assert_eq!(index, reader.stream_position().unwrap()); + + let index = reader.seek(SeekFrom::End(0)).unwrap(); + assert_eq!(index, 8); + assert_eq!(index, reader.stream_position().unwrap()); + + let index = reader.seek(SeekFrom::End(-4)).unwrap(); + assert_eq!(index, 4); + assert_eq!(index, reader.stream_position().unwrap()); + + let index = reader.seek(SeekFrom::End(-8)).unwrap(); + assert_eq!(index, 0); + assert_eq!(index, reader.stream_position().unwrap()); + + reader.seek(SeekFrom::End(i64::MIN)).unwrap_err(); + assert_eq!(index, reader.stream_position().unwrap()); + + let index = reader.seek(SeekFrom::Start(0)).unwrap(); + assert_eq!(index, 0); + assert_eq!(index, reader.stream_position().unwrap()); + + reader.seek(SeekFrom::Current(-1)).unwrap_err(); + assert_eq!(index, reader.stream_position().unwrap()); + + let index = reader.seek(SeekFrom::Current(2)).unwrap(); + assert_eq!(index, 2); + assert_eq!(index, reader.stream_position().unwrap()); + + let index = reader.seek(SeekFrom::Current(2)).unwrap(); + assert_eq!(index, 4); + assert_eq!(index, reader.stream_position().unwrap()); + + let index = reader.seek(SeekFrom::Current(-2)).unwrap(); + assert_eq!(index, 2); + assert_eq!(index, reader.stream_position().unwrap()); + + let index = reader.seek(SeekFrom::Current(-2)).unwrap(); + assert_eq!(index, 0); + assert_eq!(index, reader.stream_position().unwrap()); + + let index = reader.seek(SeekFrom::Current(i64::MAX)).unwrap(); + assert_eq!(index, 8); + assert_eq!(index, reader.stream_position().unwrap()); + + let index = reader.seek(SeekFrom::Current(-1)).unwrap(); + assert_eq!(index, 7); + assert_eq!(index, reader.stream_position().unwrap()); + } } diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index 59ad8b79b5..4de36f2d94 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -22,7 +22,7 @@ use std::{ use unwrap_infallible::UnwrapInfallible; use zenoh_buffers::{ buffer::{Buffer, SplitBuffer}, - reader::{HasReader, Reader}, + reader::HasReader, writer::HasWriter, ZBufReader, ZSlice, }; @@ -171,11 +171,6 @@ where let t = ZSerde.deserialize(&kpld).ok()?; Some(t) } - - fn size_hint(&self) -> (usize, Option) { - let remaining = self.reader.remaining(); - (remaining, Some(remaining)) - } } impl FromIterator for Payload From 140526b6881ef3ddcc7536ccf879cd86692e36bf Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 9 Apr 2024 17:14:18 +0200 Subject: [PATCH 09/19] impl Seek for PayloadReader --- zenoh/src/payload.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index 4de36f2d94..7e42b4564a 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -14,7 +14,6 @@ //! Payload primitives. use crate::buffers::ZBuf; -use std::io::Read; use std::marker::PhantomData; use std::{ borrow::Cow, convert::Infallible, fmt::Debug, ops::Deref, string::FromUtf8Error, sync::Arc, @@ -143,6 +142,12 @@ impl std::io::Read for PayloadReader<'_> { } } +impl std::io::Seek for PayloadReader<'_> { + fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result { + std::io::Seek::seek(&mut self.0, pos) + } +} + /// An iterator that implements [`std::iter::Iterator`] trait to iterate on values `T` in a [`Payload`]. /// Note that [`Payload`] contains a serialized version of `T` and iterating over a [`Payload`] performs lazy deserialization. #[repr(transparent)] @@ -285,6 +290,8 @@ impl Deserialize<'_, [u8; N]> for ZSerde { type Error = ZDeserializeError; fn deserialize(self, v: &Payload) -> Result<[u8; N], Self::Error> { + use std::io::Read; + if v.0.len() != N { return Err(ZDeserializeError); } From 2dceb52b4db864d4616fd0ca1d271d2e423752cc Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 9 Apr 2024 17:40:18 +0200 Subject: [PATCH 10/19] Fix tests --- zenoh/src/payload.rs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index 7e42b4564a..a63d19d4a9 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -19,6 +19,7 @@ use std::{ borrow::Cow, convert::Infallible, fmt::Debug, ops::Deref, string::FromUtf8Error, sync::Arc, }; use unwrap_infallible::UnwrapInfallible; +use zenoh_buffers::ZBufWriter; use zenoh_buffers::{ buffer::{Buffer, SplitBuffer}, reader::HasReader, @@ -148,6 +149,21 @@ impl std::io::Seek for PayloadReader<'_> { } } +/// A writer that implements [`std::io::Write`] trait to write into a [`Payload`]. +#[repr(transparent)] +#[derive(Debug)] +pub struct PayloadWriter<'a>(ZBufWriter<'a>); + +impl std::io::Write for PayloadWriter<'_> { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + std::io::Write::write(&mut self.0, buf) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + /// An iterator that implements [`std::iter::Iterator`] trait to iterate on values `T` in a [`Payload`]. /// Note that [`Payload`] contains a serialized version of `T` and iterating over a [`Payload`] performs lazy deserialization. #[repr(transparent)] @@ -1205,7 +1221,7 @@ mod tests { let v: [usize; 5] = [0, 1, 2, 3, 4]; println!("Serialize:\t{:?}", v); let p = Payload::from_iter(v.iter()); - println!("Deserialize:\t{:?}", p); + println!("Deserialize:\t{:?}\n", p); for (i, t) in p.iter::().enumerate() { assert_eq!(i, t); } @@ -1213,7 +1229,7 @@ mod tests { let mut v = vec![[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]; println!("Serialize:\t{:?}", v); let p = Payload::from_iter(v.drain(..)); - println!("Deserialize:\t{:?}", p); + println!("Deserialize:\t{:?}\n", p); let mut iter = p.iter::<[u8; 4]>(); assert_eq!(iter.next().unwrap(), [0, 1, 2, 3]); assert_eq!(iter.next().unwrap(), [4, 5, 6, 7]); @@ -1226,8 +1242,8 @@ mod tests { hm.insert(0, 0); hm.insert(1, 1); println!("Serialize:\t{:?}", hm); - let p = Payload::from_iter(hm.drain()); - println!("Deserialize:\t{:?}", p); + let p = Payload::from_iter(hm.clone().drain()); + println!("Deserialize:\t{:?}\n", p); let o = HashMap::from_iter(p.iter::<(usize, usize)>()); assert_eq!(hm, o); } From c2c6217bcb894fe7d5319249c3b46f2f5230d998 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 9 Apr 2024 18:07:06 +0200 Subject: [PATCH 11/19] Add SHM support for deserializer --- Cargo.lock | 1 + examples/Cargo.toml | 7 +++- examples/examples/z_sub.rs | 1 - examples/examples/z_sub_shm.rs | 66 ++++++++++++++++++++++++++++++++++ zenoh/src/payload.rs | 23 ++++++++++++ 5 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 examples/examples/z_sub_shm.rs diff --git a/Cargo.lock b/Cargo.lock index 3f74af9ed1..a9d327a978 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4612,6 +4612,7 @@ dependencies = [ "zenoh", "zenoh-collections", "zenoh-ext", + "zenoh-shm", ] [[package]] diff --git a/examples/Cargo.toml b/examples/Cargo.toml index fc1db17fe8..fb9c4c481d 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -27,7 +27,7 @@ readme = "README.md" publish = false [features] -shared-memory = ["zenoh/shared-memory"] +shared-memory = ["zenoh-shm","zenoh/shared-memory"] unstable = ["zenoh/unstable"] transport_unixpipe = ["zenoh/transport_unixpipe"] @@ -52,6 +52,7 @@ log = { workspace = true } zenoh = { workspace = true } zenoh-collections = { workspace = true } zenoh-ext = { workspace = true } +zenoh-shm = { workspace = true, optional = true } [dev-dependencies] rand = { workspace = true, features = ["default"] } @@ -96,6 +97,10 @@ required-features = ["shared-memory"] name = "z_sub" path = "examples/z_sub.rs" +[[example]] +name = "z_sub_shm" +path = "examples/z_sub_shm.rs" + [[example]] name = "z_pull" path = "examples/z_pull.rs" diff --git a/examples/examples/z_sub.rs b/examples/examples/z_sub.rs index fbce562c2e..299f0c8f49 100644 --- a/examples/examples/z_sub.rs +++ b/examples/examples/z_sub.rs @@ -32,7 +32,6 @@ async fn main() { let session = zenoh::open(config).res().await.unwrap(); println!("Declaring Subscriber on '{}'...", &key_expr); - let subscriber = session.declare_subscriber(&key_expr).res().await.unwrap(); println!("Press CTRL-C to quit..."); diff --git a/examples/examples/z_sub_shm.rs b/examples/examples/z_sub_shm.rs new file mode 100644 index 0000000000..630876f287 --- /dev/null +++ b/examples/examples/z_sub_shm.rs @@ -0,0 +1,66 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// +use clap::Parser; +use zenoh::config::Config; +use zenoh::prelude::r#async::*; +use zenoh_examples::CommonArgs; +use zenoh_shm::SharedMemoryBuf; + +#[tokio::main] +async fn main() { + // Initiate logging + env_logger::init(); + + let (mut config, key_expr) = parse_args(); + + // A probing procedure for shared memory is performed upon session opening. To enable `z_pub_shm` to operate + // over shared memory (and to not fallback on network mode), shared memory needs to be enabled also on the + // subscriber side. By doing so, the probing procedure will succeed and shared memory will operate as expected. + config.transport.shared_memory.set_enabled(true).unwrap(); + + println!("Opening session..."); + let session = zenoh::open(config).res().await.unwrap(); + + println!("Declaring Subscriber on '{}'...", &key_expr); + let subscriber = session.declare_subscriber(&key_expr).res().await.unwrap(); + + println!("Press CTRL-C to quit..."); + while let Ok(sample) = subscriber.recv_async().await { + match sample.payload().deserialize::() { + Ok(payload) => println!( + ">> [Subscriber] Received {} ('{}': '{:02x?}')", + sample.kind(), + sample.key_expr().as_str(), + payload.as_slice() + ), + Err(e) => { + println!(">> [Subscriber] Not a SharedMemoryBuf: {:?}", e); + } + } + } +} + +#[derive(clap::Parser, Clone, PartialEq, Eq, Hash, Debug)] +struct SubArgs { + #[arg(short, long, default_value = "demo/example/**")] + /// The Key Expression to subscribe to. + key: KeyExpr<'static>, + #[command(flatten)] + common: CommonArgs, +} + +fn parse_args() -> (Config, KeyExpr<'static>) { + let args = SubArgs::parse(); + (args.common.into(), args.key) +} diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index a63d19d4a9..b05cf868a8 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -1000,6 +1000,29 @@ impl From for Payload { } } +#[cfg(feature = "shared-memory")] +impl Deserialize<'_, SharedMemoryBuf> for ZSerde { + type Error = ZDeserializeError; + + fn deserialize(self, v: &Payload) -> Result { + for zs in v.0.zslices() { + if let Some(shmb) = zs.downcast_ref::() { + return Ok(shmb.clone()); + } + } + Err(ZDeserializeError) + } +} + +#[cfg(feature = "shared-memory")] +impl TryFrom for SharedMemoryBuf { + type Error = ZDeserializeError; + + fn try_from(value: Payload) -> Result { + ZSerde.deserialize(&value) + } +} + // Tuple impl Serialize<(A, B)> for ZSerde where From e4ee3069e4cff58a79e983d2bdb9c357a5975177 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 9 Apr 2024 18:30:30 +0200 Subject: [PATCH 12/19] Fix SharedMemoryBuf deserialize --- zenoh/src/payload.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index b05cf868a8..1cb9fae783 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -1005,7 +1005,9 @@ impl Deserialize<'_, SharedMemoryBuf> for ZSerde { type Error = ZDeserializeError; fn deserialize(self, v: &Payload) -> Result { - for zs in v.0.zslices() { + // A SharedMemoryBuf is expected to have only one slice + let mut zslices = v.0.zslices(); + if let Some(zs) = zslices.next() { if let Some(shmb) = zs.downcast_ref::() { return Ok(shmb.clone()); } From cf861e1ecaa75930488e72b8288027828d1eadb4 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 9 Apr 2024 18:36:10 +0200 Subject: [PATCH 13/19] Fix clippy examples --- examples/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index fb9c4c481d..4a4a4fef3e 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -100,6 +100,7 @@ path = "examples/z_sub.rs" [[example]] name = "z_sub_shm" path = "examples/z_sub_shm.rs" +required-features = ["shared-memory"] [[example]] name = "z_pull" From 28e23ab3c2713c2b65e331a7d432c0c2856c63b9 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 9 Apr 2024 19:42:25 +0200 Subject: [PATCH 14/19] Add writer method to payload --- zenoh/src/payload.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index 1cb9fae783..f8af7e182a 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -14,9 +14,9 @@ //! Payload primitives. use crate::buffers::ZBuf; -use std::marker::PhantomData; use std::{ - borrow::Cow, convert::Infallible, fmt::Debug, ops::Deref, string::FromUtf8Error, sync::Arc, + borrow::Cow, convert::Infallible, fmt::Debug, marker::PhantomData, ops::Deref, + string::FromUtf8Error, sync::Arc, }; use unwrap_infallible::UnwrapInfallible; use zenoh_buffers::ZBufWriter; @@ -57,7 +57,7 @@ impl Payload { Self(ZBuf::empty()) } - /// Create a [`Payload`] from any type `T` that can implements [`Into`]. + /// Create a [`Payload`] from any type `T` that implements [`Into`]. pub fn new(t: T) -> Self where T: Into, @@ -80,7 +80,7 @@ impl Payload { PayloadReader(self.0.reader()) } - /// Build a [`Payload`] from a [`Reader`]. This operation copies data from the reader. + /// Build a [`Payload`] from a generic reader implementing [`std::io::Read`]. This operation copies data from the reader. pub fn from_reader(mut reader: R) -> Result where R: std::io::Read, @@ -103,6 +103,11 @@ impl Payload { } } + /// Get a [`PayloadWriter`] implementing [`std::io::Write`] trait. + pub fn writer(&mut self) -> PayloadWriter<'_> { + PayloadWriter(self.0.writer()) + } + /// Encode an object of type `T` as a [`Value`] using the [`ZSerde`]. /// /// ```rust @@ -733,7 +738,7 @@ impl Serialize<&serde_json::Value> for ZSerde { fn serialize(self, t: &serde_json::Value) -> Self::Output { let mut payload = Payload::empty(); - serde_json::to_writer(payload.0.writer(), t)?; + serde_json::to_writer(payload.writer(), t)?; Ok(payload) } } From 042964e11e8a6aa423611f669b33e5426bdfd7bc Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 10 Apr 2024 11:49:09 +0200 Subject: [PATCH 15/19] Add ZSlice payload support --- commons/zenoh-buffers/src/zbuf.rs | 41 ++++- commons/zenoh-buffers/src/zslice.rs | 4 + .../zenoh-collections/src/single_or_vec.rs | 3 + zenoh/src/payload.rs | 174 +++++++++++++++--- 4 files changed, 187 insertions(+), 35 deletions(-) diff --git a/commons/zenoh-buffers/src/zbuf.rs b/commons/zenoh-buffers/src/zbuf.rs index 6fded06ae7..cfface650a 100644 --- a/commons/zenoh-buffers/src/zbuf.rs +++ b/commons/zenoh-buffers/src/zbuf.rs @@ -17,7 +17,7 @@ use crate::{ buffer::{Buffer, SplitBuffer}, reader::{BacktrackableReader, DidntRead, DidntSiphon, HasReader, Reader, SiphonableReader}, writer::{BacktrackableWriter, DidntWrite, HasWriter, Writer}, - ZSlice, + ZSlice, ZSliceBuffer, }; use alloc::{sync::Arc, vec::Vec}; use core::{cmp, iter, mem, num::NonZeroUsize, ops::RangeBounds, ptr}; @@ -60,6 +60,21 @@ impl ZBuf { } } + pub fn to_zslice(&self) -> ZSlice { + let mut slices = self.zslices(); + match self.slices.len() { + 0 => ZSlice::empty(), + // SAFETY: it's safe to use unwrap_unchecked() beacuse we are explicitly checking the length is 1. + 1 => unsafe { slices.next().unwrap_unchecked().clone() }, + _ => slices + .fold(Vec::new(), |mut acc, it| { + acc.extend(it.as_slice()); + acc + }) + .into(), + } + } + pub fn splice>(&mut self, erased: Range, replacement: &[u8]) { let start = match erased.start_bound() { core::ops::Bound::Included(n) => *n, @@ -201,15 +216,31 @@ impl PartialEq for ZBuf { } // From impls +impl From for ZBuf { + fn from(t: ZSlice) -> Self { + let mut zbuf = ZBuf::empty(); + zbuf.push_zslice(t); + zbuf + } +} + +impl From> for ZBuf +where + T: ZSliceBuffer + 'static, +{ + fn from(t: Arc) -> Self { + let zslice: ZSlice = t.into(); + Self::from(zslice) + } +} + impl From for ZBuf where - T: Into, + T: ZSliceBuffer + 'static, { fn from(t: T) -> Self { - let mut zbuf = ZBuf::empty(); let zslice: ZSlice = t.into(); - zbuf.push_zslice(zslice); - zbuf + Self::from(zslice) } } diff --git a/commons/zenoh-buffers/src/zslice.rs b/commons/zenoh-buffers/src/zslice.rs index c15cbc6828..05c77cac7d 100644 --- a/commons/zenoh-buffers/src/zslice.rs +++ b/commons/zenoh-buffers/src/zslice.rs @@ -114,6 +114,10 @@ impl ZSlice { } } + pub fn empty() -> Self { + unsafe { ZSlice::new_unchecked(Arc::new([]), 0, 0) } + } + /// # Safety /// This function does not verify wether the `start` and `end` indexes are within the buffer boundaries. /// If a [`ZSlice`] is built via this constructor, a later access may panic if `start` and `end` indexes are out-of-bound. diff --git a/commons/zenoh-collections/src/single_or_vec.rs b/commons/zenoh-collections/src/single_or_vec.rs index ceb43e4025..ed82bf49af 100644 --- a/commons/zenoh-collections/src/single_or_vec.rs +++ b/commons/zenoh-collections/src/single_or_vec.rs @@ -182,14 +182,17 @@ impl SingleOrVec { self.vectorize().insert(at, value); } } + enum DrainInner<'a, T> { Vec(alloc::vec::Drain<'a, T>), Single(&'a mut SingleOrVecInner), Done, } + pub struct Drain<'a, T> { inner: DrainInner<'a, T>, } + impl<'a, T> Iterator for Drain<'a, T> { type Item = T; diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index f8af7e182a..1b91757329 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -91,11 +91,11 @@ impl Payload { } /// Get a [`PayloadReader`] implementing [`std::io::Read`] trait. - pub fn iter<'a, T>(&'a self) -> PayloadIterator<'a, T> + pub fn iter(&self) -> PayloadIterator<'_, T> where - T: TryFrom, - ZSerde: Deserialize<'a, T>, - >::Error: Debug, + T: for<'b> TryFrom<&'b Payload>, + for<'b> ZSerde: Deserialize<'b, T>, + for<'b> >::Error: Debug, { PayloadIterator { reader: self.0.reader(), @@ -126,14 +126,23 @@ impl Payload { } /// Decode an object of type `T` from a [`Value`] using the [`ZSerde`]. - /// See [encode](Value::encode) for an example. pub fn deserialize<'a, T>(&'a self) -> ZResult where ZSerde: Deserialize<'a, T>, >::Error: Debug, { - let t: T = ZSerde.deserialize(self).map_err(|e| zerror!("{:?}", e))?; - Ok(t) + ZSerde + .deserialize(self) + .map_err(|e| zerror!("{:?}", e).into()) + } + + /// Decode an object of type `T` from a [`Value`] using the [`ZSerde`]. + pub fn into<'a, T>(&'a self) -> T + where + ZSerde: Deserialize<'a, T, Error = Infallible>, + >::Error: Debug, + { + ZSerde.deserialize(self).unwrap_infallible() } } @@ -181,10 +190,10 @@ where _t: PhantomData, } -impl<'a, T> Iterator for PayloadIterator<'a, T> +impl Iterator for PayloadIterator<'_, T> where - ZSerde: for<'b> Deserialize<'b, T>, - >::Error: Debug, + for<'a> ZSerde: Deserialize<'a, T>, + for<'a> >::Error: Debug, { type Item = T; @@ -278,6 +287,55 @@ impl From<&Payload> for ZBuf { } } +// ZSlice +impl Serialize for ZSerde { + type Output = Payload; + + fn serialize(self, t: ZSlice) -> Self::Output { + Payload::new(t) + } +} + +impl From for Payload { + fn from(t: ZSlice) -> Self { + ZSerde.serialize(t) + } +} + +impl Serialize<&ZSlice> for ZSerde { + type Output = Payload; + + fn serialize(self, t: &ZSlice) -> Self::Output { + Payload::new(t.clone()) + } +} + +impl From<&ZSlice> for Payload { + fn from(t: &ZSlice) -> Self { + ZSerde.serialize(t) + } +} + +impl Deserialize<'_, ZSlice> for ZSerde { + type Error = Infallible; + + fn deserialize(self, v: &Payload) -> Result { + Ok(v.0.to_zslice()) + } +} + +impl From for ZSlice { + fn from(value: Payload) -> Self { + ZBuf::from(value).to_zslice() + } +} + +impl From<&Payload> for ZSlice { + fn from(value: &Payload) -> Self { + ZSerde.deserialize(value).unwrap_infallible() + } +} + // [u8; N] impl Serialize<[u8; N]> for ZSerde { type Output = Payload; @@ -515,7 +573,6 @@ impl From<&str> for Payload { } } -// Cow impl<'a> Serialize> for ZSerde { type Output = Payload; @@ -1069,16 +1126,16 @@ where } } -impl<'a, A, B> Deserialize<'a, (A, B)> for ZSerde +impl Deserialize<'_, (A, B)> for ZSerde where - A: TryFrom, - >::Error: Debug, - B: TryFrom, - >::Error: Debug, + for<'a> A: TryFrom<&'a Payload>, + for<'a> >::Error: Debug, + for<'b> B: TryFrom<&'b Payload>, + for<'b> >::Error: Debug, { type Error = ZError; - fn deserialize(self, payload: &'a Payload) -> Result<(A, B), Self::Error> { + fn deserialize(self, payload: &Payload) -> Result<(A, B), Self::Error> { let codec = Zenoh080::new(); let mut reader = payload.0.reader(); @@ -1088,18 +1145,18 @@ where let bbuf: ZBuf = codec.read(&mut reader).map_err(|e| zerror!("{:?}", e))?; let bpld = Payload::new(bbuf); - let a = A::try_from(apld).map_err(|e| zerror!("{:?}", e))?; - let b = B::try_from(bpld).map_err(|e| zerror!("{:?}", e))?; + let a = A::try_from(&apld).map_err(|e| zerror!("{:?}", e))?; + let b = B::try_from(&bpld).map_err(|e| zerror!("{:?}", e))?; Ok((a, b)) } } impl TryFrom for (A, B) where - A: TryFrom, - >::Error: Debug, - B: TryFrom, - >::Error: Debug, + A: for<'a> TryFrom<&'a Payload>, + for<'a> >::Error: Debug, + for<'b> B: TryFrom<&'b Payload>, + for<'b> >::Error: Debug, { type Error = ZError; @@ -1108,6 +1165,20 @@ where } } +impl TryFrom<&Payload> for (A, B) +where + for<'a> A: TryFrom<&'a Payload>, + for<'a> >::Error: Debug, + for<'b> B: TryFrom<&'b Payload>, + for<'b> >::Error: Debug, +{ + type Error = ZError; + + fn try_from(value: &Payload) -> Result { + ZSerde.deserialize(value) + } +} + // For convenience to always convert a Value in the examples #[derive(Debug, Clone, PartialEq, Eq)] pub enum StringOrBase64 { @@ -1142,12 +1213,9 @@ impl std::fmt::Display for StringOrBase64 { impl From<&Payload> for StringOrBase64 { fn from(v: &Payload) -> Self { use base64::{engine::general_purpose::STANDARD as b64_std_engine, Engine}; - match v.deserialize::>() { - Ok(s) => StringOrBase64::String(s.into_owned()), - Err(_) => { - let cow: Cow<'_, [u8]> = Cow::from(v); - StringOrBase64::Base64(b64_std_engine.encode(cow)) - } + match v.deserialize::() { + Ok(s) => StringOrBase64::String(s), + Err(_) => StringOrBase64::Base64(b64_std_engine.encode(v.into::>())), } } } @@ -1157,7 +1225,7 @@ mod tests { fn serializer() { use super::Payload; use rand::Rng; - use zenoh_buffers::ZBuf; + use zenoh_buffers::{ZBuf, ZSlice}; const NUM: usize = 1_000; @@ -1276,5 +1344,51 @@ mod tests { println!("Deserialize:\t{:?}\n", p); let o = HashMap::from_iter(p.iter::<(usize, usize)>()); assert_eq!(hm, o); + + let mut hm: HashMap> = HashMap::new(); + hm.insert(0, vec![0u8; 8]); + hm.insert(1, vec![1u8; 16]); + println!("Serialize:\t{:?}", hm); + let p = Payload::from_iter(hm.clone().drain()); + println!("Deserialize:\t{:?}\n", p); + let o = HashMap::from_iter(p.iter::<(usize, Vec)>()); + assert_eq!(hm, o); + + let mut hm: HashMap> = HashMap::new(); + hm.insert(0, vec![0u8; 8]); + hm.insert(1, vec![1u8; 16]); + println!("Serialize:\t{:?}", hm); + let p = Payload::from_iter(hm.clone().drain()); + println!("Deserialize:\t{:?}\n", p); + let o = HashMap::from_iter(p.iter::<(usize, Vec)>()); + assert_eq!(hm, o); + + let mut hm: HashMap = HashMap::new(); + hm.insert(0, ZSlice::from(vec![0u8; 8])); + hm.insert(1, ZSlice::from(vec![1u8; 16])); + println!("Serialize:\t{:?}", hm); + let p = Payload::from_iter(hm.clone().drain()); + println!("Deserialize:\t{:?}\n", p); + let o = HashMap::from_iter(p.iter::<(usize, ZSlice)>()); + assert_eq!(hm, o); + + let mut hm: HashMap = HashMap::new(); + hm.insert(0, ZBuf::from(vec![0u8; 8])); + hm.insert(1, ZBuf::from(vec![1u8; 16])); + println!("Serialize:\t{:?}", hm); + let p = Payload::from_iter(hm.clone().drain()); + println!("Deserialize:\t{:?}\n", p); + let o = HashMap::from_iter(p.iter::<(usize, ZBuf)>()); + assert_eq!(hm, o); + + use std::borrow::Cow; + let mut hm: HashMap> = HashMap::new(); + hm.insert(0, vec![0u8; 8]); + hm.insert(1, vec![1u8; 16]); + println!("Serialize:\t{:?}", hm); + let p = Payload::from_iter(hm.clone().iter().map(|(k, v)| (k, Cow::from(v)))); + println!("Deserialize:\t{:?}\n", p); + let o = HashMap::from_iter(p.iter::<(usize, Vec)>()); + assert_eq!(hm, o); } } From abded105583f165d939ac9b24174e6a65b11abbb Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 10 Apr 2024 11:58:42 +0200 Subject: [PATCH 16/19] Improve payload --- zenoh/src/payload.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index 1b91757329..aed0d15834 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -1225,6 +1225,7 @@ mod tests { fn serializer() { use super::Payload; use rand::Rng; + use std::borrow::Cow; use zenoh_buffers::{ZBuf, ZSlice}; const NUM: usize = 1_000; @@ -1302,10 +1303,21 @@ mod tests { serialize_deserialize!(String, ""); serialize_deserialize!(String, String::from("abcdefghijklmnopqrstuvwxyz")); + // Cow + serialize_deserialize!(Cow, Cow::from("")); + serialize_deserialize!( + Cow, + Cow::from(String::from("abcdefghijklmnopqrstuvwxyz")) + ); + // Vec serialize_deserialize!(Vec, vec![0u8; 0]); serialize_deserialize!(Vec, vec![0u8; 64]); + // Cow<[u8]> + serialize_deserialize!(Cow<[u8]>, Cow::from(vec![0u8; 0])); + serialize_deserialize!(Cow<[u8]>, Cow::from(vec![0u8; 64])); + // ZBuf serialize_deserialize!(ZBuf, ZBuf::from(vec![0u8; 0])); serialize_deserialize!(ZBuf, ZBuf::from(vec![0u8; 64])); @@ -1381,7 +1393,6 @@ mod tests { let o = HashMap::from_iter(p.iter::<(usize, ZBuf)>()); assert_eq!(hm, o); - use std::borrow::Cow; let mut hm: HashMap> = HashMap::new(); hm.insert(0, vec![0u8; 8]); hm.insert(1, vec![1u8; 16]); From 7d9d57c2b2ef023a0c5887efb092250f2ff2ef44 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 10 Apr 2024 13:03:54 +0200 Subject: [PATCH 17/19] Fix tests --- zenoh/src/payload.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/zenoh/src/payload.rs b/zenoh/src/payload.rs index aed0d15834..eac4f58e7c 100644 --- a/zenoh/src/payload.rs +++ b/zenoh/src/payload.rs @@ -14,6 +14,7 @@ //! Payload primitives. use crate::buffers::ZBuf; +use std::str::Utf8Error; use std::{ borrow::Cow, convert::Infallible, fmt::Debug, marker::PhantomData, ops::Deref, string::FromUtf8Error, sync::Arc, @@ -494,7 +495,7 @@ impl<'a> Deserialize<'a, Cow<'a, [u8]>> for ZSerde { type Error = Infallible; fn deserialize(self, v: &'a Payload) -> Result, Self::Error> { - Ok(Cow::from(v)) + Ok(v.0.contiguous()) } } @@ -602,16 +603,19 @@ impl From<&Cow<'_, str>> for Payload { } impl<'a> Deserialize<'a, Cow<'a, str>> for ZSerde { - type Error = FromUtf8Error; + type Error = Utf8Error; - fn deserialize(self, v: &Payload) -> Result, Self::Error> { - let v: String = Self.deserialize(v)?; - Ok(Cow::Owned(v)) + fn deserialize(self, v: &'a Payload) -> Result, Self::Error> { + let v: Cow<[u8]> = Self.deserialize(v).unwrap_infallible(); + let _ = core::str::from_utf8(v.as_ref())?; + // SAFETY: &str is &[u8] with the guarantee that every char is UTF-8 + // As implemented internally https://doc.rust-lang.org/std/str/fn.from_utf8_unchecked.html. + Ok(unsafe { core::mem::transmute(v) }) } } impl<'a> TryFrom<&'a Payload> for Cow<'a, str> { - type Error = FromUtf8Error; + type Error = Utf8Error; fn try_from(value: &'a Payload) -> Result { ZSerde.deserialize(value) @@ -1301,14 +1305,11 @@ mod tests { // String serialize_deserialize!(String, ""); - serialize_deserialize!(String, String::from("abcdefghijklmnopqrstuvwxyz")); + serialize_deserialize!(String, String::from("abcdef")); // Cow serialize_deserialize!(Cow, Cow::from("")); - serialize_deserialize!( - Cow, - Cow::from(String::from("abcdefghijklmnopqrstuvwxyz")) - ); + serialize_deserialize!(Cow, Cow::from(String::from("abcdef"))); // Vec serialize_deserialize!(Vec, vec![0u8; 0]); From 27063b6fd2f15be36aa3988c37cf1cbb46933c40 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 10 Apr 2024 15:10:17 +0200 Subject: [PATCH 18/19] Integrating #918 --- commons/zenoh-buffers/src/lib.rs | 12 ++ commons/zenoh-buffers/src/zbuf.rs | 213 +++++++++++++++--------------- 2 files changed, 117 insertions(+), 108 deletions(-) diff --git a/commons/zenoh-buffers/src/lib.rs b/commons/zenoh-buffers/src/lib.rs index eae7f1715c..117fb412b7 100644 --- a/commons/zenoh-buffers/src/lib.rs +++ b/commons/zenoh-buffers/src/lib.rs @@ -199,6 +199,18 @@ pub mod reader { fn rewind(&mut self, mark: Self::Mark) -> bool; } + pub trait AdvanceableReader: Reader { + fn skip(&mut self, offset: usize) -> Result<(), DidntRead>; + fn backtrack(&mut self, offset: usize) -> Result<(), DidntRead>; + fn advance(&mut self, offset: isize) -> Result<(), DidntRead> { + if offset > 0 { + self.skip(offset as usize) + } else { + self.backtrack((-offset) as usize) + } + } + } + #[derive(Debug, Clone, Copy)] pub struct DidntSiphon; diff --git a/commons/zenoh-buffers/src/zbuf.rs b/commons/zenoh-buffers/src/zbuf.rs index cfface650a..f3621049b0 100644 --- a/commons/zenoh-buffers/src/zbuf.rs +++ b/commons/zenoh-buffers/src/zbuf.rs @@ -15,7 +15,10 @@ use crate::ZSliceKind; use crate::{ buffer::{Buffer, SplitBuffer}, - reader::{BacktrackableReader, DidntRead, DidntSiphon, HasReader, Reader, SiphonableReader}, + reader::{ + AdvanceableReader, BacktrackableReader, DidntRead, DidntSiphon, HasReader, Reader, + SiphonableReader, + }, writer::{BacktrackableWriter, DidntWrite, HasWriter, Writer}, ZSlice, ZSliceBuffer, }; @@ -433,43 +436,74 @@ impl<'a> io::Read for ZBufReader<'a> { } } -#[cfg(feature = "std")] -impl<'a> io::Seek for ZBufReader<'a> { - fn seek(&mut self, pos: io::SeekFrom) -> io::Result { - // Compute the index - let len = self.inner.len(); - let index = match pos { - io::SeekFrom::Start(pos) => pos.try_into().unwrap_or(i64::MAX), - io::SeekFrom::End(pos) => { - pos + i64::try_from(len) - .map_err(|e| io::Error::new(io::ErrorKind::UnexpectedEof, e))? - } - io::SeekFrom::Current(pos) => { - pos + i64::try_from(len - self.remaining()) - .map_err(|e| io::Error::new(io::ErrorKind::UnexpectedEof, e))? +impl<'a> AdvanceableReader for ZBufReader<'a> { + fn skip(&mut self, offset: usize) -> Result<(), DidntRead> { + let mut remaining_offset = offset; + while remaining_offset > 0 { + let s = self.inner.slices.get(self.cursor.slice).ok_or(DidntRead)?; + let remains_in_current_slice = s.len() - self.cursor.byte; + let advance = remaining_offset.min(remains_in_current_slice); + remaining_offset -= advance; + self.cursor.byte += advance; + if self.cursor.byte == s.len() { + self.cursor.slice += 1; + self.cursor.byte = 0; } - }; + } + Ok(()) + } - let index = usize::try_from(index) - .map_err(|e| io::Error::new(io::ErrorKind::UnexpectedEof, e))? - .min(len); - - // Seek the position - let mut left = index; - let mut pos = ZBufPos { slice: 0, byte: 0 }; - while let Some(slice) = self.inner.slices.get(pos.slice) { - let len = slice.len(); - if len >= left { - pos.byte = left; - self.cursor = pos; - return Ok(index as u64); - } else { - left -= len; + fn backtrack(&mut self, offset: usize) -> Result<(), DidntRead> { + let mut remaining_offset = offset; + while remaining_offset > 0 { + let backtrack = remaining_offset.min(self.cursor.byte); + remaining_offset -= backtrack; + self.cursor.byte -= backtrack; + if self.cursor.byte == 0 { + if self.cursor.slice == 0 { + break; + } + self.cursor.slice -= 1; + self.cursor.byte = self + .inner + .slices + .get(self.cursor.slice) + .ok_or(DidntRead)? + .len(); } - pos.slice += 1; } + if remaining_offset == 0 { + Ok(()) + } else { + Err(DidntRead) + } + } +} - Err(io::ErrorKind::UnexpectedEof.into()) +#[cfg(feature = "std")] +impl<'a> io::Seek for ZBufReader<'a> { + fn seek(&mut self, pos: io::SeekFrom) -> io::Result { + let current_pos = self + .inner + .slices() + .take(self.cursor.slice) + .fold(0, |acc, s| acc + s.len()) + + self.cursor.byte; + let current_pos = i64::try_from(current_pos) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("{}", e)))?; + + let offset = match pos { + std::io::SeekFrom::Start(s) => i64::try_from(s).unwrap_or(i64::MAX) - current_pos, + std::io::SeekFrom::Current(s) => s, + std::io::SeekFrom::End(s) => self.inner.len() as i64 + s - current_pos, + }; + match self.advance(offset as isize) { + Ok(()) => Ok((offset + current_pos) as u64), + Err(_) => Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "InvalidInput", + )), + } } } @@ -745,80 +779,43 @@ mod tests { #[cfg(feature = "std")] #[test] fn zbuf_seek() { - use crate::reader::HasReader; - use std::io::{Seek, SeekFrom}; - - use super::{ZBuf, ZSlice}; - - let slice: ZSlice = [0u8, 1, 2, 3, 4, 5, 6, 7].to_vec().into(); - - let mut zbuf = ZBuf::empty(); - zbuf.push_zslice(slice.subslice(0, 1).unwrap()); - zbuf.push_zslice(slice.subslice(1, 4).unwrap()); - zbuf.push_zslice(slice.subslice(4, 8).unwrap()); - - let mut reader = zbuf.reader(); - - let index = reader.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(index, 0); - assert_eq!(index, reader.stream_position().unwrap()); - - let index = reader.seek(SeekFrom::Start(4)).unwrap(); - assert_eq!(index, 4); - assert_eq!(index, reader.stream_position().unwrap()); - - let index = reader.seek(SeekFrom::Start(8)).unwrap(); - assert_eq!(index, 8); - assert_eq!(index, reader.stream_position().unwrap()); - - let index = reader.seek(SeekFrom::Start(u64::MAX)).unwrap(); - assert_eq!(index, 8); - assert_eq!(index, reader.stream_position().unwrap()); - - let index = reader.seek(SeekFrom::End(0)).unwrap(); - assert_eq!(index, 8); - assert_eq!(index, reader.stream_position().unwrap()); - - let index = reader.seek(SeekFrom::End(-4)).unwrap(); - assert_eq!(index, 4); - assert_eq!(index, reader.stream_position().unwrap()); - - let index = reader.seek(SeekFrom::End(-8)).unwrap(); - assert_eq!(index, 0); - assert_eq!(index, reader.stream_position().unwrap()); - - reader.seek(SeekFrom::End(i64::MIN)).unwrap_err(); - assert_eq!(index, reader.stream_position().unwrap()); - - let index = reader.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(index, 0); - assert_eq!(index, reader.stream_position().unwrap()); - - reader.seek(SeekFrom::Current(-1)).unwrap_err(); - assert_eq!(index, reader.stream_position().unwrap()); - - let index = reader.seek(SeekFrom::Current(2)).unwrap(); - assert_eq!(index, 2); - assert_eq!(index, reader.stream_position().unwrap()); - - let index = reader.seek(SeekFrom::Current(2)).unwrap(); - assert_eq!(index, 4); - assert_eq!(index, reader.stream_position().unwrap()); - - let index = reader.seek(SeekFrom::Current(-2)).unwrap(); - assert_eq!(index, 2); - assert_eq!(index, reader.stream_position().unwrap()); - - let index = reader.seek(SeekFrom::Current(-2)).unwrap(); - assert_eq!(index, 0); - assert_eq!(index, reader.stream_position().unwrap()); - - let index = reader.seek(SeekFrom::Current(i64::MAX)).unwrap(); - assert_eq!(index, 8); - assert_eq!(index, reader.stream_position().unwrap()); - - let index = reader.seek(SeekFrom::Current(-1)).unwrap(); - assert_eq!(index, 7); - assert_eq!(index, reader.stream_position().unwrap()); + use super::{HasReader, ZBuf}; + use crate::reader::Reader; + use std::io::Seek; + + let mut buf = ZBuf::empty(); + buf.push_zslice([0u8, 1u8, 2u8, 3u8].into()); + buf.push_zslice([4u8, 5u8, 6u8, 7u8, 8u8].into()); + buf.push_zslice([9u8, 10u8, 11u8, 12u8, 13u8, 14u8].into()); + let mut reader = buf.reader(); + + assert_eq!(reader.stream_position().unwrap(), 0); + assert_eq!(reader.read_u8().unwrap(), 0); + assert_eq!(reader.seek(std::io::SeekFrom::Current(6)).unwrap(), 7); + assert_eq!(reader.read_u8().unwrap(), 7); + assert_eq!(reader.seek(std::io::SeekFrom::Current(-5)).unwrap(), 3); + assert_eq!(reader.read_u8().unwrap(), 3); + assert_eq!(reader.seek(std::io::SeekFrom::Current(10)).unwrap(), 14); + assert_eq!(reader.read_u8().unwrap(), 14); + reader.seek(std::io::SeekFrom::Current(100)).unwrap_err(); + + assert_eq!(reader.seek(std::io::SeekFrom::Start(0)).unwrap(), 0); + assert_eq!(reader.read_u8().unwrap(), 0); + assert_eq!(reader.seek(std::io::SeekFrom::Start(12)).unwrap(), 12); + assert_eq!(reader.read_u8().unwrap(), 12); + assert_eq!(reader.seek(std::io::SeekFrom::Start(15)).unwrap(), 15); + reader.read_u8().unwrap_err(); + reader.seek(std::io::SeekFrom::Start(100)).unwrap_err(); + + assert_eq!(reader.seek(std::io::SeekFrom::End(0)).unwrap(), 15); + reader.read_u8().unwrap_err(); + assert_eq!(reader.seek(std::io::SeekFrom::End(-5)).unwrap(), 10); + assert_eq!(reader.read_u8().unwrap(), 10); + assert_eq!(reader.seek(std::io::SeekFrom::End(-15)).unwrap(), 0); + assert_eq!(reader.read_u8().unwrap(), 0); + reader.seek(std::io::SeekFrom::End(-20)).unwrap_err(); + + assert_eq!(reader.seek(std::io::SeekFrom::Start(10)).unwrap(), 10); + reader.seek(std::io::SeekFrom::Current(-100)).unwrap_err(); } } From a1c2a024e6343222eb110595ee166804b24d0397 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 10 Apr 2024 15:12:25 +0200 Subject: [PATCH 19/19] Fix ZBur io::Read impl --- commons/zenoh-buffers/src/zbuf.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/commons/zenoh-buffers/src/zbuf.rs b/commons/zenoh-buffers/src/zbuf.rs index f3621049b0..4a655ce36a 100644 --- a/commons/zenoh-buffers/src/zbuf.rs +++ b/commons/zenoh-buffers/src/zbuf.rs @@ -428,10 +428,7 @@ impl<'a> io::Read for ZBufReader<'a> { fn read(&mut self, buf: &mut [u8]) -> io::Result { match ::read(self, buf) { Ok(n) => Ok(n.get()), - Err(_) => Err(io::Error::new( - io::ErrorKind::UnexpectedEof, - "UnexpectedEof", - )), + Err(_) => Ok(0), } } }